Typescript 转换工具 babel-loader 和 ts-loader
ts-loader
ts-loader
是一个 Webpack 加载器,用于将 TypeScript 代码编译成 JavaScript 代码,以便浏览器能够理解和运行。ts-loader 使用 tsc 将 TypeScript 转换为 JavaScript,并能处理相关的类型检查和源映射。它常与 Webpack 一起使用,是 TypeScript 项目中进行模块打包和编译的工具之一。
- 安装
**ts-loader**
和**typescript**
首先,您需要安装 ts-loader
和 typescript
作为项目的依赖项:
npm install -D ts-loader typescript
- 配置 Webpack
在 Webpack 的配置文件 webpack.config.js
中,使用 ts-loader
来处理 .ts
和 .tsx
文件。以下是一个基本的配置示例:
const path = require('path');
module.exports = {
entry: './src/index.ts', // 入口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
extensions: ['.ts', '.tsx', '.js'], // 解析这些扩展名的文件
},
module: {
rules: [
{
test: /\.tsx?$/, // 匹配 .ts 或 .tsx 文件
use: 'ts-loader', // 使用 ts-loader 进行编译
exclude: /node_modules/, // 排除 node_modules 文件夹
},
],
},
};
- 配置 TypeScript
你还需要配置 TypeScript 编译器,通常通过一个 tsconfig.json
文件。这个文件告诉 TypeScript 编译器如何编译代码。使用 ts-loader 必须要配置 tsconfig.json
文件。
示例 tsconfig.json
文件:
{
"compilerOptions": {
"target": "es5",
"module": "es6",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
这个配置文件指定了编译选项,例如目标 JavaScript 版本、模块系统等,并指定了要编译的文件和排除的文件。
- 目标代码 src/index.ts
// 类型定义
const test: number = 1
// 特殊符号
const a = {b: 2}
console.log(a?.b);
// 箭头函数
const say = () => {
console.log("hello world");
};
say();
// 高版本语法
const d = [1, 2, 3]
console.log(d.includes(4))
// 枚举值
enum Color {
Red
}
console.log(Color.Red)
- 编译结果
!function () {
"use strict";
var o, l = {b: 2};
console.log(null == l ? void 0 : l.b),
console.log("hello world"),
console.log([1, 2, 3].includes(4)),
function (o) {
o[o.Red = 0] = "Red"
}(o || (o = {})), console.log(o.Red)
}();
可以总结一下 ts-loader 做了如下工作
- 编译耗时
平均在 600ms+
babel-loader
同样的工程,使用 babel-loader 编译需要做如下修改
- webpack 配置
{
module: {
rules: [
{
test: /\.js$|\.tsx?$/, // 匹配 .js .ts 或 .tsx 文件
use: 'babel-loader', // 使用 babel-loader 进行编译
exclude: /node_modules/, // 排除 node_modules 文件夹
},
],
},
};
- .babelrc
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": 3
}],
"@babel/preset-typescript"
]
}
babel 编译 ts 文件,需要用到 @babel/preset-typescript
,babel/preset-typescript 不需要 tsconfig.json
再补充说一下 @babel/plugin-transform-typescript
@babel/preset-typescript
包含 @babel/plugin-transform-typescript
@babel/plugin-transform-typescript 无法处理,可选链接 (?.), 空合并(??)和类属性(this.#x)等语法。如果您想转译这些功能,我们建议使用preset-env和preset-typescript。
- 编译结果
var n = {b: 2};
console.log(null == n ? void 0 : n.b),
console.log("hello world"),
console.log([1, 2, 3].includes(4));
var o = function (t) {
return t[t.Red = 0] = "Red", t
}(o || {});
console.log(o.Red)
可以总结一下
babel-loader 和 ts-loader 的编译结果无差别,并且加入了 pollyfill。但是babel-loader 只负责编译,不负责类型检查。所以类型错误不会报错。
比如 上面的代码 加一句 console.log(c) 。ts-laoder 会报错,babel-loader 则不会。
- 编译耗时
babel-loader 的编译耗时在 500ms+,比 ts-loader 快 10% ~ 20%。
对比
通过两张图能明显看出来,ts-loader 的优势在于编译过程中进行语法检测,问题能提前暴露。
babel-loader 的优势在于可以按需添加polyfill,编译不进行语法检测,同时,打包速度比 ts-laoder 快
ts-loader 如果如果需要添加 polyfill,也可以和 babel-loader 同时使用
{
test: /\.tsx?$/,
use: [
'babel-loader',
'ts-loader',
],
exclude: /node_modules/,
},
先用 ts-loader 编译一遍,再用 babel-loader 处理 pollyfill。但是这样编译耗时将成倍提升。得不偿失。
总结
整体来看,使用 babel-loader 替代 ts-loader 效率更高,功能更强。而类型检查可以交给编辑器来检查,或者在git commit 钩子处做检查。