webpack4和webpack5的区别?
- webpack5增加了模块联邦。
- webpack5默认支持了持久化缓存。
- webpack5支持commonJS的TreeShaking,webpack4只支持esm的TreeShaking。
- webpack5内置资源模块,无需file-loader处理资源。
什么叫持久化缓存?
首次构建生成完整缓存,后续构建基于 ModuleGraph
和 ChunkGraph
的哈希比对,仅重新编译变更文件及其依赖,跳过未改动模块解析,开发模式下默认启用内存缓存,生产模式需手动配置持久化策略。
缓存分为内存缓存和磁盘持久化缓存,默认方式为内存缓存,磁盘持久化缓存需要手动配置。
// Webpack 4 通过插件实现缓存机制
const HardSourcePlugin = require('hard-source-webpack-plugin');
module.exports = {
plugins: [
new HardSourcePlugin() // 默认缓存路径:node_modules/.cache/hard-source
]
};
// Webpack 5 默认的内存缓存
module.exports = {
cache: { type: 'memory' }
};
// Webpack 5 手动配置的持久化磁盘缓存
module.exports = {
cache: {
type: 'filesystem',
cacheDirectory: 'node_modules/.cache/webpack', // 默认路径
buildDependencies: { config: [__filename] } // 依赖配置触发缓存失效
}
};
webpack5如何实现的TreeShaking?
Webpack 5 通过静态分析模块依赖关系和标记未使用代码两阶段实现 Tree Shaking,最终借助压缩工具(如 Terser)删除无效代码。 Webpack 5可以针对commonJS做TreeShaking,但是效果有限,仅支持静态导出模式。
// commonJS
// 导出对象(属性引用难以追踪,无法 Tree Shaking)
module.exports = {
add: (a, b) => a + b,
sub: (a, b) => a - b
};
// 动态导入(无法 Tree Shaking)
let utils;
if (Math.random() > 0.5) {
utils = require('./utilsA');
} else {
utils = require('./utilsB');
}
// 静态导出(可能触发 Tree Shaking)
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
exports.add = add; // 若未被引用,可能被删除
exports.sub = sub; // 若仅 `add` 被使用,`sub` 可能被标记未使用
// ESM
// 推荐(可Tree Shaking)
import { debounce } from 'lodash-es';
// 不推荐(全量引入)
import _ from 'lodash';
静态分析模块依赖关系
- 构建过程中生成 ModuleGraph 和 ChunkGraph,记录模块导入/导出关系。
- 通过AST解析识别出纯函数和无副作用的代码块。
标记未使用代码
- 根据模块间的引用链,在ModuleGraph对象中设置_usedInRuntime属性,标记未被实际调用的导出变量。
webpack有哪些优化?
- TreeShaking
- 构建缓存