Skip to content

bundle 和 transform 两种模式讨论 #301

@imsobear

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?
  • 面向用户端应该如何设计?

附录

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