Bundle your TypeScript library with no config, powered by esbuild.
tsup 号称不用配置文件,打包 ts 库。底层为 esbuild。tsup 这么宣传,说明它肯定做了很多预设封装,不需要太多配置,开箱即用。
rollup 已经是牛夫人了。
node.js 支持的都能打包,.js, .json, .mjs.。加上 ts 相关的 .ts, .tsx。
npm i tsup -D
# Or Yarn
yarn add tsup --dev
# Or pnpm
pnpm add tsup -D
tsup [...files]
默认打包到 ./dist
。
能自动排除 node_modules 。
默认打包为 es5,CommonJS,
eg:
tsup src/index.ts src/cli.ts
生成 dist/index.js 和 dist/cli.js
可选的文件:
–config 配置项可指定配置文件。
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts'],
splitting: false,
sourcemap: true,
clean: true,
})
导出一个函数,tsup cli 会执行这个函数。
import { defineConfig } from 'tsup'
export default defineConfig((options) => {
return {
minify: !options.watch,
}
})
{
"tsup": {
"entry": ["src/index.ts"],
"splitting": false,
"sourcemap": true,
"clean": true
},
"scripts": {
"build": "tsup"
}
}
export default defineConfig({
// Outputs `dist/a.js` and `dist/b.js`.
entry: ['src/a.ts', 'src/b.ts'],
// Outputs `dist/foo.js` and `dist/bar.js`
entry: {
foo: 'src/a.ts',
bar: 'src/b.ts',
},
})
tsup index.ts --dts
tsup index.ts --sourcemap
支持 esm,cjs (默认) 和 iife。
tsup src/index.ts --format esm,cjs,iife
dist
├── index.mjs # esm
├── index.global.js # iife
└── index.js # cjs
如果 package.json 的 type 字段为 module。命名会变成:
dist
├── index.js # esm
├── index.global.js # iife
└── index.cjs # cjs
export default defineConfig({
outExtension({ format }) {
return {
js: `.${format}.js`,
}
},
})
默认支持 esm ,并且默认开启。CJS 需要 --splitting 手动开启。
target 选项配置构建产物的目标环境,默认是 node16。
可支持:
target 也可以指定 js 版本,比如 es2020,es5。
esbuild 是不支持 es5 的。tsup 是怎么做到的?
tsup 会先打包成 es2020,然后通过 SWC 转成 es5。
tsup src/index.ts --env.NODE_ENV production
当入口文件如 src/cli.ts 包含 hashbang(即 #!/bin/env node)时,tsup 会自动使输出文件可执行,因此您无需运行 chmod +x dist/cli.js 来手动设置可执行权限。
tsup src/index.ts --watch
可选择忽视监听的文件:
tsup src src/index.ts --watch --ignore-watch folder1 --ignore-watch folder2
这在监听模式下非常有用。
import { defineConfig } from 'tsup'
export default defineConfig({
async onSuccess() {
// Start some long running task
// Like a server
const server = http.createServer((req, res) => {
res.end('Hello World!')
})
server.listen(3000)
return () => {
server.close()
}
},
})
tsup src/index.ts --minify
默认是用 esbuild 压缩,也可以用 terser 代替。前提必须安装 terser。
npm install -D terser
tsup src/index.ts --minify terser
在 tsup.config.js 中,您可以传递 terserOptions,这些选项将原封不动地传递给 terser.minify。
esbuild 提供这些 loader:
type Loader =
| 'js'
| 'jsx'
| 'ts'
| 'tsx'
| 'css'
| 'json'
| 'text'
| 'base64'
| 'file'
| 'dataurl'
| 'binary'
| 'copy'
| 'default'
会发现上面没有图片的 loader,但我们可以指定 loader 去处理某些后缀的图片。
import { defineConfig } from 'tsup'
export default defineConfig({
loader: {
'.jpg': 'base64',
'.webp': 'file',
},
})
esbuild 默认开启了 tree shaking。但它的 tree shaking 可能有问题,所以 tsup 允许你选择 rollup 的 tree shaking 去替代 esbuild。
import { defineConfig } from 'tsup'
export default defineConfig({
treeshake: true, // 使用 rollup tree shaking
}
esbuild 之所以快,就是因为它不会执行 ts 类型检查。你应该依靠 IDE 在完成类型检查。
如果你就想在构建时,执行类型检查,可以开启 --dts。
它会生成类型声明文件,自然也会进行类型检查。
传递 --metafile 标志,告诉 esbuild 以 JSON 格式生成一些关于构建的元数据。您可以将输出文件提供给像 bundle buddy 这样的分析工具,以可视化您的包中的模块以及每个模块占用多少空间。
生成的文件格式为:metafile-{format}.json
。eg:metafile-cjs.json
import { defineConfig } from 'tsup'
export default defineConfig({
esbuildPlugins: [YourPlugin],
esbuildOptions(options, context) {
options.define.foo = '"bar"'
},
})
shims 本意为垫片,类似于补丁的意思
启用此选项将在构建 esm/cjs 项目时填充一些代码以使其工作。
例如 __dirname
仅在 cjs 模块中可用,而 import.meta.url
仅在 esm 模块中可用。打完补丁后,esm 中就也能用 __dirname 了。
import { defineConfig } from 'tsup'
export default defineConfig({
shims: true,
})
打的补丁具体是什么样的?
CJS 项目会添加如下代码:
// import.meta.url:
(import.meta.url as typeof document) === "undefined"
? new URL("file:" + __filename).href
: (document.currentScript && document.currentScript.src) || new URL("main.js", document.baseURI).href;
esm 项目会添加如下代码:
// __dirname
path.dirname(fileURLToPath(import.meta.url))
vite 早期配置中就得使用这段代码。现在可以直接使用 __diranme 了。看来也是把这段代码作为了补丁,默认提供。
使用 --publicDir 将 ./public 文件夹内的文件复制到输出目录。
您还可以使用 --publicDir [dir]
来选择一个自定义目录。
tsup 提供了 js API,可以在 js 中使用。
import { build } from 'tsup'
await build({
entry: ['src/index.ts'],
sourcemap: true,
dts: true,
})
当您在 tsconfig 中启用了emitDecoratorMetadata
时,通常会发生这种情况。
在这种模式下,我们使用 SWC 将装饰器转换为 JavaScript,因此导出的类型将被消除,这就是为什么 esbuild 无法找到相应的导出。
您可以通过将 import 语句从 import {SomeType}
更改为import {type SomeType}
或import type {SomeType}
来修复此问题。