webpack打包ts的两种方案对比
一、内容简介
目前大家常用的webpack打包ts主要为两种方案:
- ts-loader:将ts转为js,再使用babel将js转为低版本js;
- @babel/preset-typescript:它是直接移除TypeScript,转为JS,这使得它的编译速度飞快,并且只需要管理Babel一个编译器就行了。
二、方案对比
首先我们需要安装 webpack、webpack-cli、typescript
随便写一点ts,用于打包测试:
// index.ts
class Student {
name: string
age: Number
constructor(name: string, age: Number) {
this.name = name
this.age = age
}
greet() {
console.log(`Hello, my name is ${this.name}`)
}
}
const testPromise = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1')
}, 1000)
})
}
const studentA = new Student('a', 20)
studentA.greet()
testPromise().then(data => {
console.log('data', data)
})
1.使用方法法对比
1)ts-loader:
先安装ts-loader
: npm install ts-loader --save-dev
在项目中配置webpack.config.js:
const path = require('path')
module.exports = {
mode: 'development',
entry: './index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
resolve: {
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
}
]
},
plugins: []
}
然后需要设置tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"sourceMap": true,
"target": "es5",
"lib": [
"es5",
"dom",
"es2015.promise"
]
}
}
lib根据具体代码和应用场景还可以配置其他参数:


npm install core-js
npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
设置.babelrc;
{
"presets": [
[
"@babel/preset-env",
{
"corejs": "3",
"useBuiltIns": "usage"
}
]
]
}
在webpack.config.js中设置babel-loader处理js
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: ['babel-loader', 'ts-loader']
}
]
},
再进行打包:

2)@babel/preset-typescript:
和上面相关bebel的插件基本相同
npm install core-js
npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
npm install --save-dev @babel/preset-typescript
就多了@babel/preset-typescript
webpack.config.js中直接使用了babel-loader:
const path = require('path')
module.exports = {
mode: 'development',
entry: './index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: ['babel-loader']
}
]
},
plugins: []
}
.babelrc中也只多了@babel/preset-typescript
{
"presets": [
[
"@babel/preset-env",
{
"corejs": "3",
"useBuiltIns": "usage"
}
],
"@babel/preset-typescript"
]
}
执行打包,发现bundle.js也是打包了promise。
这里使用@babel/preset-typescript
的时候专门删了tsconfig.js,发现依然可以打包成功,但是ts-loader
是一定要设置tsconfig.js的,因为我只是做了一下测试,所以删除了,实际项目中还是要设置tsconfig.js。
2.打包时间比较
两种方案中ts代码完全相同:
ts-loader
打包时间:

@babel/preset-typescript
打包时间:

3.使用ts封装npm工具包比较
如果我们需要使用ts来开发一些开发工具类的npm包,其实我还是更推荐
ts-loader
:
我们先新建两个项目,然后随便写一点测试代码:
1)ts-loader:
ts-build-loader
为使用ts-loader
来开发的npm包:
ts-build-loader: src/index.ts
export function addFn(a: number, b: number): number {
return a + b
}
在tsconfig.json中需要配置生成项目声明文件:
{
"compilerOptions": {
"module": "commonjs",
"sourceMap": true,
"target": "es5",
"declaration": true, // 将生成.d.ts文件
"outDir": "./dist",
"lib": [
"es5",
"dom",
"es2015.promise"
]
},
"exclude": [
"./dist"
]
}
此时我们可以执行npm run build
看下打包后的代码:


2)@babel/preset-typescript:
ts-build-babel
为使用@babel/preset-typescript
开发的npm包:
ts-build-babel: src/index.ts
export function subFn(a: number, b: number): number {
return a - b
}
执行npm run build
:

tsconfig.json
中已经设置了declaration
也没有项目的声明文件。
最后我们在这两个项目的package.json
中设置main为打包后的js:

再新建一个项目test-ts-npm
用来测试我们的工具是否可用,我们分别在ts-build-loader
和ts-build-babel
中执行npm link
,然后在test-ts-npm
中分别链接这两个包:npm link ts-build-loader、 npm link ts-build-babel
在项目中简单的安装一下ts,新建一个index.ts
文件测试前面写好的两个工具类:
test-ts-npm: index.ts
import { addFn } from 'ts-build-loader'
import { subFn } from 'ts-build-babel'
let n = addFn(1, 1)
let m = subFn(1, 1)
console.log(n)
console.log(m)
先tsc index.ts
编译一下ts,再node index.js
执行编译后的js:

ts-loader
开发npm包的优势是很明显的:
- 1.引入没有报错提示:

ts-loader
打包项目时由于已经生成了声明文件,所以引用这里不会报无法找到模块之类的错误;
- 2.更智能的错误提示:当我们故意写错一个参数时:

ts-loader
打包后的代码由于有index.d.ts文件,在我们使用方法不正确时,vscode会提示相应错误信息。在开发过程中,这样的方式显然是更合理的。
最后,还有了几个疑问没有解决:
-
@babel/preset-typescript
能否通过设置生成项目的声明文件;
-
- 其实打包后的代码可以明显看到:使用
ts-loader
打包后的代码量会远大于@babel/preset-typescript
打包的代码,目前还没找到合理的解释和处理方法
- 其实打包后的代码可以明显看到:使用
希望有哪位大佬知道的话可以评论在下面,如果我找到了相关问题的资料也会第一时间完善和补充。
三、总结
通过上面的两种方案对比:
如果项目为业务逻辑相关,可以考虑使用@babel/preset-typescript
,配置更简单,而且打包速度更快一点; 而ts-loader
在配置过程中还是遇到了很多坑的,比如tsconfig.json
中lib没有设置导致报错,而在转es5实际也是用babel处理es6的方案解决,这样直接使用@babel/preset-typescript
感觉会更加清晰。
如果是作为开发相关工具包或组件库,还是更推荐用ts-loader
,这种打包后可以自动生成项目声明文件,在其他项目中引入会有更友好的开发体验。
转载自:https://juejin.cn/post/6844904160375078925