webpack5 中 对commonjs 的tree-shaking

815 阅读1分钟

0 省流结论

webpack5 支持了对Commonjs的tree-shaking,依据见文档

省流贴图

WechatIMG528.png

1 前情提要

在某平台买了webpack5学习资料,发现tree-shaking章节和文档冲突,因为很尊重作者(ta的webpack文章水平有一说一的质量好)然后自己做了小demo验证了下

2 验证过程

foo.js文件

const testCommon1 = 'abcs'

const testCommon2 = '2333'

module.exports.a = testCommon1
module.exports.c = testCommon2

index.js文件

 
import { test1,test2 } from './esm.js'


let a = require('./foo.js').a


console.log(test1,a)

webpack.config.js

const path = require("path");

debugger

module.exports = {
  entry: "./index.js",
  devtool: false,
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    clean: true,
  },
  // mode:'production',
  mode: "development",
  optimization: {
    usedExports: true,
  },
};

分析bundle.js产物得出webpack内部会对未使用的导出做了处理,即标记 __webpack_unuesed_export __ 现阶段webpack内部对commonjs的tree-shaking大家可以理解为不那么彻底的“tree-shaking”

因为对于esm其实webpack是有 harmony 处理,后面有时间会出两者的内部区别

/***/ "./foo.js":
/*!****************!*\
  !*** ./foo.js ***!
  \****************/
/***/ ((module) => {

var __webpack_unused_export__;
const testCommon1 = 'abcs'

const testCommon2 = '2333'

module.exports.a = testCommon1
__webpack_unused_export__ = testCommon2


/***/ })

3 追溯源码

目录位置 webpack-main/lib/dependencies/CommonJsExportsDependency.js

主要函数片段,贴图如下

SCR-20220922-lia.png

这里着重介绍一下InitFragments对象, 它是之前webpack版本DependenciesBlockVariables中的替代品。

官网中单纯介绍它为可以删除重复数据,实际上它做的东西很多,比如基于esm的tree-shaking有着harmony 处理,深扒出 在harmony中核心对象HarmonyExportInitFragment是基于InitFragments,来做无效代码的删除

SCR-20220922-m9j.png

4 总结之外的东西

在当今前端世界中 构建打包编译工具层出不穷,变着花样惹人眼的时候,也有老伙伴默默的给你升级套餐,比如webpack5有很多值得bb的点,比如长期缓存,原生worker的支持,模块联邦等等。