1. 前论
webpack的树摇功能早就深入人心,而 动态导入也随着vue&react的splitChunks在各个页面中进入了应用 在webpack.5中的production模式下,各种优化配置已经自动开启,其中就包括了splitChunks
但是在学习这两者的过程中,我也产生了一个疑问,
tree-shaking是基于esmodule的功能,因为esmodule是静态结构,可以直接分析导入和导出的关系,从而去除没有被使用的“死代码”- 动态导入的语法为
import(xxxx),也是esmodule语法的一部分- 所以
tree-shaking和import(xxxx)会不会产生某种化学反应,
先说结论: 正如第一段所说,
import(xxxx)是splitChunks的作用,作为入口文件,默认不走tree-shaking的逻辑
2. 代码演示
1. 单独配置 tree-shaking
// webpack.prod.js
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
/** 方便查看打包结果,使用 development 模式 */
mode: 'development',
devtool: false,
optimization: {
usedExports: true,
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: false,
}),
]
},
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: 'public',
globOptions: {
ignore: ['**/index.html']
}
}
]
}),
]
}
// index.js
import { foo1 } from './utils/utils.js'
console.log(foo1(10))
// utils.js
export function foo1(num) {
return console.log('foo1', num)
}
export function foo2(num) {
return console.log('foo2', num)
}
使用以上代码以及配置执行
build,查看结果
通过以上两张截图可以发现,utils 的 foo2 函数被 删除
tree-shaking配置成功
2. 配置 tree-shaking & import(xxx)
webpack 配置不变, index.js 代码做修改
const button = document.createElement('button');
document.body.appendChild(button);
button.textContent = '点我'
button.addEventListener('click', () => {
import('./utils/utils').then(({foo1}) => {
console.log('res====', foo1);
})
})
使用以上代码以及配置执行
build,查看结果
index.2c5c8666.bundle.js
src_utils_utils_js.2927d5b7.bundle.js
虽然在 index 中 只使用了
foo1但是foo2也依旧被打包进入,而且在 index 中的使用方式也是n.foo1(这里的 n 是 webpack 生成代码之后的 module,包含了导入文件信息)
3. 部分动态导入 & 配置 tree-shaking & import(xxx)
当前代码目录结构如下:
// utils2.js
export function foo3(num) {
return console.log('foo3', num)
}
export function foo4(num) {
return console.log('foo4', num)
}
// index.js
const button = document.createElement('button');
document.body.appendChild(button);
button.textContent = '点我'
const input = document.createElement('input');
document.body.appendChild(input);
button.addEventListener('click', () => {
const path = input.value;
import(`./utils/${path}`).then(res => {
console.log('res====', res);
})
})
使用以上代码以及配置执行
build,查看结果
其实光从截图 + 上文的分析,就可以看出,
webpack无脑地将utils目录下的 所有文件都进行了一个打包,并分别为不同的chunk模块
4. 全动态导入 & 配置 tree-shaking & import(xxx)
// index.js
const button = document.createElement('button');
document.body.appendChild(button);
button.textContent = '点我'
const input = document.createElement('input');
document.body.appendChild(input);
button.addEventListener('click', () => {
const path = input.value;
import(path).then(res => {
console.log('res====', res);
})
})
其实不用我截图,到了这一步,所有人也能猜出
webpack会怎么打包,那就是.....
不打包
而输入
utils模块尝试导入的 做法也会导致报错
结论就是,基础终究是没学扎实。。。