Skip to content

bundle 和 transform 两种模式讨论 #301

Description

@imsobear

名词解释

  • bundle:将 src 下所有文件打包并编译成一个文件比如 dist/index.js
  • transform:将 src 下的文件一个一个编译并复制到 lib 或者其他目录

方案对比

transform bundle
tree-shaking 强 差
是否有些写法限制 需要主动添加 .js 后缀 不需要
bundless 接入 文件数量爆炸 文件可能很大
多端代码移除 不好做 简单
组件库 简单 不好做

transform 和 bundle 两种模式下,都支持对 JavaScript 代码的移除。而对于 css、png 有 sideEffects 的资源 tree-shaking 能力,bundle 模式无法在构建时移除。

社区现状

bundle 方案:

tsdx

  • 特性
  • 产物
├── index.d.ts
├── index.js
├── mylib.cjs.development.js // cjs + es5
├── mylib.cjs.development.js.map
├── mylib.cjs.production.min.js // cjs + es5
├── mylib.cjs.production.min.js.map
├── mylib.esm.js // esm + es5
└── mylib.esm.js.map
  • 技术选型
    • bundle 能力:rollup
    • tree-shaking: babel-plugin-annotate-pure-calls + babel-plugin-dev-expressions

tsup

  • 特性

    • 使用 esbuild 打包
    • 支持 iife / cjs / esm 的 bundle 输出,默认输出 cjs + esnext
  • 输出产物:配置 --target --format esm,cjs,iife

dist
├── index.global.js   // iife + esnext
├── index.js          // cjs + esnext
└── index.mjs         // esm + esnext
  • 技术选型
    • bundle 能力:esbuild
    • minify + sourcemap:esbuild
    • es5 : swc

unbuild

  • 特性
    • 支持 bundle 和 transform 编译(transform 使用 mkdist),无配置下是 bundle
// 配置文件
export default {
  entries: [
    {
      builder: 'mkdist',
      input: './src',
      outDir: './es'
    },
    {
      builder: 'rollup',
      input: './src/index',
    }
  ]
}

输出的结果:

- dist
  - index.mjs  // rollup 的bundle
- es
  - index.mjs  // 通过 mkdist 输出的 transform
  - multi.mjs

microbundle

  • 特性
    • 支持 modern 产物,此时babel 的配置为
[
	'@babel/preset-env', 
	{
		targets: { "esmodules": true }, // 这是因为支持 esm 的浏览器都支持 async
		bugfixes: true,
	}
]

Terser 使用 ecma:2017 来压缩

  • Package Exports (推荐的)
"main": "./dist/foo.umd.js", // legacy UMD output (for Node & CDN use)
"module": "./dist/foo.module.js", // legacy ES Modules output (for bundlers)
"exports": "./dist/foo.modern.js", // modern ES2017 output
  • 使用 package.json 配置输出的目录和文件名
{
  "source": "src/index.js",            // input
  "main": "dist/foo.js",               // CommonJS output bundle
  "umd:main": "dist/foo.umd.js",       // UMD output bundle
  "module": "dist/foo.m.js",           // ES Modules output bundle 
  "exports": {
    "require": "./dist/foo.js",        // CommonJS output bundle
    "default": "./dist/foo.modern.js", // Modern ES Modules output bundle
  },
  "types": "dist/foo.d.ts"             // TypeScript typings directory
}
  • 技术选型
    • bundle 能力:rolllup
    • 代码转义:babel
    • 压缩:terser

transfrom 方案:

mkdist

  • 特性

    • 支持单文件编译
    • 拷贝静态文件至目标目录
  • 技术选型

    • 文件编译:esbuild

讨论点

  • bundle 和 transform 是否可以同时启用?
  • 默认应该走 bundle 还是 transform?
  • 面向用户端应该如何设计?

附录

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions