携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
本文 webpack 版本 ^5.73.0、webpack-cli 版本 ^4.10.0
简介
前面笔者在介绍TypeScript
的时候,一直使用的是tsc
来编译我们的TypeScript
文件。但是在真实项目开发的时候,我们不会直接使用tsc
来编译我们的TypeScript
文件。一般我们都会结合webpack
等构建工具来使用。
在webpack
中,编译ts
文件有两种方式。
-
使用
ts-loader
编译。 -
使用
babel-loader
编译。
下面我们分别使用这两种方式来编译ts
。
ts-loader
我们先来说说我们熟悉的ts-loader
创建项目
首先我们创建一个文件夹,然后初始化package.json
文件。
// 创建webpacktest文件夹
mkdir webpacktest
// 进入webpacktest文件夹
cd webpacktest
// 创建package.json
npm init
创建源文件
在根目录下创建tssrc
目录,并创建index.ts
文件。
// index.ts
const age: number = 24;
console.log(age);
const say = () => {
console.log("hello world");
};
say();
const arr = [1, 2, 3];
console.log(arr.includes(4));
安装webpack 和 webpack-cli
我们本地安装webpack 和 webpack-cli
npm i webpack webpack-cli -D
安装ts-loader typescript
使用ts-loader
编译,它其实就是使用的tsc
进行编译,所以需要依赖typescript
和ts.config.json
配置文件。
我们先来安装一下
npm i ts-loader typescript
配置webpack.config.js
然后在webpack.config.js
进行配置,ts
文件使用ts-loader
进行处理。
module: {
rules: [
{
test: /\.ts$/,
use: ["ts-loader"],
exclude: /node_modules/, //排除 node_modules 目录
},
],
},
配置ts.config.json
ts.config.json
文件是必须要创建的,用来配置ts-loader
的参数。
内容可以根据自己项目具体要求来进行配置。如果对ts
的配置文件不熟悉的话可以看看笔者前面写的TypeScript学习之配置文件。
这里我们简单配置下
{
"compilerOptions": {
"target": "es5" // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
},
"exclude": ["./node_modules"]
}
编译
在package.josn
里面配置webpack
编译脚本。
"scripts": {
"webpack1": "webpack"
}
在命令行运行 npm run webpack1
就可以看到编译后的js
文件了。
因为我们配置了"target": "es5"
,所以箭头函数编译成了普通函数。
但是inclides()
,没有做任何处理。这个是不正常的,我们后面说。
生成类型申明文件
我们在ts.config.json
文件,添加生成申明文件和输出目录的配置
// ...
"declaration": true, // 生成相应的 '.d.ts' 文件
"outDir": "./tsdist" // 输出目录
再次编译
可以看到,生成了类型申明文件index1.d.ts
错误检测
再来看看静态检测方面
我们在index.ts
文件里面加一个未定义的变量a
// index.ts
// ...
console.log(a)
我们再次编译
可以看到,编译报错了,所以,使用ts-loader
编译是会进行语法检查的。
我们再来试试babel-loader
babel-loader
有了上面的基础,我们就不需要再创建项目了。这里我们直接安装需要使用到的包。
安装babel相关包
npm i babel-loader @babel/preset-env @babel/preset-typescript core-js@3 -D
配置 babel.config.json
因为预设是从后往前执行的,所以我们这里的顺序也是有讲究的。先使用@babel/preset-typescript
来识别ts
,然后使用@babel/preset-env
来编译js
并配置corejs
按需引入polyfill
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": "3"
}
],
"@babel/preset-typescript"
]
}
配置webpack.config.js
然后在webpack.config.js
进行配置,ts
文件使用babel-loader
进行处理。
module: {
rules: [
{
test: /\.ts$/,
use: ["babel-loader"],
exclude: /node_modules/, //排除 node_modules 目录
},
],
},
配置 .browserslistrc
这个主要是用来给@babel/preset-env
配置编译目标环境的。
> 0.5%
last 2 versions
Firefox ESR
编译
在命令行运行 npm run webpack
就可以看到编译后的js
文件了。
前面和使用ts-loader
一样,箭头函数被转成普通函数了。
但是它多了引入polyfill
这一步
./node_modules/core-js/internals/array-includes.js
所以使用babel-loader
来处理ts
的好处就是能动态按需引入polyfill
。这个在ts-loader
是不支持的,在ts-loader
中如果要引入polyfill
,需要在入口文件全量引入polyfill
。
如果还想进一步优化,抽离公共的辅助函数的话我们还可以配置@babel/plugin-transform-runtime
插件。这个就不再细说了。可以看看笔者前面写的webpack入门之js处理(babel、babel polyfill)。
生成类型申明文件
使用babel-loader
的时候并没有使用到tsc
,也不会读取ts.config.json
文件配置,所以使用babel-loader
是不能生成类型申明文件。
再来看看静态检测方面
错误检测
我们在index.ts
文件里面加一个未定义的变量a
// index.ts
// ...
console.log(a)
我们再次编译,没报错,对,你没看错。babel-loader
只会负责编译,并不会进行语法检查。
如果需要语法检测,需要单独配置命令
{
"scripts": {
"check": 'tsc --noEmit'
}
}
可以使用noEmit
参数,不生成输出文件来做语法检测。
这个命令可以单独跑,也可以结合git-hooks
在每次提交的时候自动运行来做检测。
总结
polyfill
ts-loader
不支持polyfill
的按需引入,如果需要polyfill
需要在入口全量引入。
babel-loader
是可以按需引入polyfill
。并且还可以配置@babel/plugin-transform-runtime
插件来抽离公共辅助函数。
类型申明文件
ts-loader
支持生成类型申明文件,只需要在ts.config.json
中配置即可。而babel-loader
不支持。
错误检测
ts-loader
支持错误检测,如果语法有问题会编译不成功。babel-loader
是不支持,需要单独利用tsc
单独配置。
因为 tsc
的类型检查是需要拿到整个工程的类型信息,需要做类型的引入、多个文件的 namespace、enum、interface
等的合并,而 babel
是单个文件编译的,不会解析其他文件的信息。所以做不到和 tsc
一样的类型检查。
语法支持
截止到目前为止,babel-loader
还不支持如下两种ts
语法。
- 常量枚举
const enum A {
X,
}
- 历史遗留风格的
import/export
语法
import foo = require(...)
和 export = foo
。
ts-loader
默认支持很多 es
的特性,但是不支持还在草案阶段的特性。babel-loader
的 preset-env
支持所有标准特性,并且还可以通过配置插件的方式来支持更多还未进入标准的特性。
{
plugins: ['@babel/proposal-xxx'],
presets: ['@babel/presets-env', {...}]
}
编译速度
ts-loader
编译速度慢,因为它有类型检查这一步。babel-loader
编译速度快。
构建体积
babel-loader
打包后的体积更小。因为它支持按需polyfill
和@babel/plugin-transform-runtime
插件的配置。
其次babel-loader
可以通过.browserslistrc
或target
精确配置需要适配的浏览器。而ts-loader
只能配置target
,其值有'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
,相对没那么精确。所以对打包体积也会有影响。
系列文章
webpack入门之css处理(css预处理器和css后置处理器)
webpack入门之js处理(babel、babel polyfill)
webpack入门之ts处理(ts-loadr和babel-loader的选择)
webpack入门之开发环境(mode、dev-server、devtool)
webpack入门之提升开发效率的几个配置(ProvidePlugin、DefinePlugin、resolve、externals)
后记
看到这,小伙伴们应该能做出选择了吧。其实也没有孰强孰弱,各有优势,小伙伴们可以根据自己项目具体情况来选择使用。
感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!