Skip to content

对象的 tree-shaking 优化

对于导入对象的 tree-shaking 效果有限,以下实例中通过结构获取对象中的属性可以正常执行 tree-shaking 优化。

rollup 支持的 tree-shaking 优化

esm 模块语法支持情况

js
// ✅ good case 1
import * as maths from './maths.js';
// ✅ good case 2
import { square } from './maths.js';
// ✅ good case 3
const { square: square2 } = await import('./maths.js');
// ✅ good case 4
import('./maths.js').then(({ square }) => console.log(square(10)));
console.log(maths.square(10), square, square2);
js
export const square = x => x * x;
export const double = x => x * 2;
export default { square, double };
js
const square = x => x * x;
var maths = /*#__PURE__*/ Object.freeze({
  __proto__: null,
  square
});
const { square: square2 } = await Promise.resolve().then(function () {
  return maths;
});
Promise.resolve()
  .then(function () {
    return maths;
  })
  .then(({ square }) => console.log(square(10)));
console.log(square(10), square, square2);
js
import a from './maths.js';
console.log(a.square(10));
js
const a = await import('./maths.js');
console.log(a.square(10));
js
import('./maths.js').then(a => console.log(a.square(10)));
js
export const square = x => x * x;
export const double = x => x * 2;
export default { square, double };
js
const square = x => x * x;
const double = x => x * 2;
var a = { square, double };
console.log(a.square(10));
js
const a = await import('./maths-BMpjz1lG.js');
console.log(a.square(10));
js
import('./maths-BMpjz1lG.js').then(a => console.log(a.square(10)));
js
const square = x => x * x;
const double = x => x * 2;
var maths = { square, double };

export { maths as default, double, square };

esm 模块支持 tree-shaking 语法小结

综上可以发现,rollup 对于 esm 模块除了对象引用外的其他导入方式均支持 tree-shaking 优化。对象引用暂时只支持 namespace object 引用的 tree-shaking 优化。

commonjs 模块语法支持情况

对于 commonjs 模块的 tree-shaking 优化,相对而言就比较严苛一些。

  1. 需要配置 strictRequiresfalseauto 来避免将 commonjs 模块进行包装处理。因为strictRequires为非true时,插件会尽可能确保转译后的esm 模块具备静态性质,详情可参考 Default Strict Requires To True 文章。
  2. 需要确保 commonjs 模块中使用 exports 语法导出。
  3. 需要确保使用 import() 方式导入模块的同时使用解构获取导出的属性值。

以下述例子作为说明,index.mjs 作为入口模块:

js
export * from './a.cjs';
js
(async () => {
  const { square } = await import('./b.cjs');
  console.log(square(10));
})();
js
const square = x => x * x;
const add = (a, b) => a + b;
const sub = (a, b) => a - b;

exports.square = square;
exports.add = add;
exports.sub = sub;
js
import commonjs from '@rollup/plugin-commonjs';

export default {
  input: {
    index: './index.mjs'
  },
  output: [
    {
      dir: 'dist/commonjs/esm',
      format: 'es',
      entryFileNames: 'output.js'
    }
  ],
  treeshake: true,
  plugins: [
    commonjs({
      strictRequires: false
    })
  ]
};
js
(async () => {
  const { square } = await import('./b-Co0LKdJH.js').then(function (n) {
    return n.b;
  });
  console.log(square(10));
})();
js
const square = x => x * x;

var square_1 = square;

var b = /*#__PURE__*/ Object.freeze({
  __proto__: null,
  square: square_1
});

export { b };

对象的深度 tree-shaking 优化

由上述可以发现,不管是处理 esm 模块还是 commonjs 模块,rollup 对于对象引用上的 tree-shaking 优化效果十分有限,暂时只支持针对 esm 模块的 namespace object 引用上的 tree-shaking 优化。同时对于 commonjs 模块的 tree-shaking 优化更为有限,主要原因还是 rollup 对对象的 tree-shaking 优化不够彻底。

feat: implement object tree-shaking PR 的提出就是实现 rollup 对对象的深度 tree-shaking 优化。

这本质上是针对 object 的深度 tree-sharking 优化,针对对象的结构属性获取做更深层次的 tree-shaking 优化。这个 PR 合并也意味对于 commonjs 模块的 tree-shaking 的更深度优化。

TODO: 待补充 object tree-shaking PR 的实现原理。

贡献者

页面历史

Discuss

根据 CC BY-SA 4.0 许可证发布。 (9037680)