想让 tsup 打包流程开口干活从 tsup 插件的四个钩子说起【免费下载链接】tsupThe simplest and fastest way to bundle your TypeScript libraries.项目地址: https://gitcode.com/gh_mirrors/ts/tsuptsup 是基于 esbuild 的 TypeScript 打包工具零配置就能同时产出 ESM/CJS。它的核心矛盾在于内置钩子覆盖不到的需求——产物占位符替换、按格式定制压缩、写盘后统计——总得有一处官方预留的插口。tsup 插件正是这套插口理解它比记住 API 更重要。tsup 插件钩子触发时机先看 tsup 层插件注意区别于透传给 esbuild 的esbuildPlugins。Plugin 接口只有一个必填字段name其余四个方法全部可选buildStart、esbuildOptions、renderChunk、buildEnd类型定义在src/plugin.ts。PluginContainer负责按序驱动它们完整链路是buildStart→进入 esbuildsetup回调里触发esbuildOptions→ esbuild 完成 resolve、transform、bundle → 拿到内存产物后对每个 chunk 循环执行renderChunk→ 写盘 → 全部写完再跑buildEnd此时能拿到writtenFiles列表。图中的bundle 还是 external判定发生在 esbuild 的 resolve 阶段由内置externalPlugin完成不属于Plugin接口暴露的能力。也就是说模块级拦截谁进包、谁外置走noExternal/external配置或 esbuild 层插件产物级改写代码长什么样才是tsup 插件的主场。四个钩子按生命周期分组buildStartesbuild 启动前此时产物还不存在。典型场景是前置校验缺文件、缺依赖提前报错和构建期埋点属于开跑之前。esbuildOptionsesbuild 初始化阶段能直接改options比如加define、调target。官方swc-target就靠它把es5/es3临时改写成es2020让 esbuild 先跑通。renderChunk每个 chunk 生成后、写盘前逐 chunk 串行触发。拿得到当前code、path、map返回新code即可替换该 chunk还能设置info.mode改文件权限。产物干预基本都发生在这一层terser 压缩、shebang 权限位、CJS 互操作尾行全在此完成。buildEnd全部文件写盘后触发只关心写出去了什么。典型用途是体积报告、把writtenFiles上报到 CI。tsup 官方插件速览内置插件都收在 src/plugins/按主钩子归位插件主钩子用途源文件swc-targetesbuildOptions renderChunktarget 为 es5/es3 时交给 swc 降级src/plugins/swc-target.tsterserrenderChunkminify: terser时用 terser 压缩src/plugins/terser.tstree-shakingrenderChunk再套一层 Rollup 做二次 tree shakingsrc/plugins/tree-shaking.tscjs-splittingrenderChunkesbuild 不支持 CJS 分割手动 ESM 转 CJSsrc/plugins/cjs-splitting.tscjs-interoprenderChunk默认导出时补module.exports exports.defaultsrc/plugins/cjs-interop.tsshebangrenderChunk产物以#!开头则写0o755权限src/plugins/shebang.tssize-reporterbuildEnd汇总打印各产物体积src/plugins/size-reporter.ts一眼可见绝大多数官方插件都压在renderChunk上说明它是扩展收益最高的钩子。在 tsup.config.ts 挂载 tsup 自定义插件一个完整小场景产物里的APP_VERSION占位符希望写盘前被替换成真实版本号。步骤是新建插件文件实现钩子 → 在tsup.config.ts的plugins数组挂载 → 验证输出。// plugins/replace.ts import type { Plugin } from tsup const replacePlugin (): Plugin ({ name: replace-placeholder, renderChunk(code, info) { if (!info.path.endsWith(.js)) return return { code: code.replace(/APP_VERSION/g, 1.0.0) } }, }) export default replacePlugin注意renderChunk只对 JS/CSS chunk 触发src/plugin.ts里isJS || isCSS的过滤逻辑所以按扩展名判断是常规操作需要改写 sourcemap 时再返回map否则沿用原 map。// tsup.config.ts import { defineConfig } from tsup import replacePlugin from ./plugins/replace export default defineConfig({ entry: src/index.ts, plugins: [replacePlugin()], })跑一次npx tsup后grep APP_VERSION dist/index.js应无输出grep 1.0.0 dist/index.js命中占位符位置说明替换发生在写盘前。下一步顺着钩子调用链读一遍src/plugin.ts的PluginContainer比任何 API 表都快。挑一个官方实现精读src/plugins/cjs-interop.ts只有 26 行是最干净的renderChunk范例。涉及模块级拦截时再翻 docs/README.md 里 Custom esbuild plugin and options 一节区分esbuildPlugins与plugins两条路线。【免费下载链接】tsupThe simplest and fastest way to bundle your TypeScript libraries.项目地址: https://gitcode.com/gh_mirrors/ts/tsup创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?