webpack

5 阅读2分钟

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
  • 构建缓存