Skip to content

按需加载

tree shaking

背景

js
// common.js
export const a = 'a'
js
// index.js
import { a } from './common.js'

// 无用代码
export const b = 'b'
console.log(a)

问题:变量 b 虽然没有用到,但是打包时依然会保留。 解决:通过 Tree Shaking,对没有用到的代码进行标记清除,达到减小打包体积的目的。

Tree Shaking 原理

实际应用:组件库按需加载

ES module

  • 组件库导出需要有 es 模块。如 dist/es/组件内容
  • 外部引入时,需要可以指向 es,通过 package.json 里的 module 字段制定。
  • package.json 中需要指定 sideEffects,标识副作用。
  • 项目中使用时,需要保证编译后都是 es 模块。比如 tsconfig.json 里的 module@babel/preset-env 里的 module 属性, 都有可能更改模块形式。
  • 例如:lodash => lodash-es

babel-plugin-import

import { Button } from 'xxx' 改写为 import { Button } from 'xxx/button'

  • 类型可以不考虑,因为经过 ts-loader 后,类型被剔除了。
  • 对于不规则的组件名称,需要通过 customName 方法来自定义相应的引入路径。
  • 例如:loadash 引入路径转换

side effects

  • package.json side effects
    • 引入外部模块 import 'test' 会查找外部模块的 package.json 看是否有 sideEffects
    • 引入没有导出:import './index.js' 会查找自身 package.json 看是否有 sideEffects
    • 导出了但是没有使用:export { xx } from 'xxx' 会查找自身 package.json 看是否有 sideEffects
    • 如果导出被使用或者有 sideEffects 的文件会被计算分析。

cjs 与 es 区别

  • cjs 为值拷贝(浅拷贝),es 为引用

todo

  • commonjs 是如何也支持 tree shaking 的?

参考