跳到主要内容

配置项

2024年11月23日
柏拉文
越努力,越幸运

一、layer


二、import


三、filename


四、dependOn


4.1 认识

entry.dependOnWebpack entry 配置的一项功能,用于定义某个入口依赖于其他入口的共享模块。它通过显式声明入口间的依赖关系,优化打包效率,减少重复代码,并实现更精细的代码分割。 entry.dependOn 的作用如下:

  1. 减少重复代码: 当多个入口共享相同的依赖时,dependOn 可以将这些依赖提取到一个单独的共享文件中。

  2. 优化打包: 避免在多个入口的打包文件中重复引入相同的依赖,提升构建速度和加载效率。

3., 显式定义依赖关系: 通过声明入口间的依赖,清晰地组织项目结构。

4.2 语法

entry: {
common: "./src/common/index.ts",
pageA: { import: "./src/pageA/index.js", dependOn: "common" },
pageB: { import: "./src/pageB/index.js", dependOn: "common" },
}
entry: {
common: ["react", "react-dom", "lodash", "ahooks"],
pageA: { import: "./src/pageA/index.js", dependOn: "common" },
pageB: { import: "./src/pageB/index.js", dependOn: "common" },
}
entry: {
pageA: { import: "./src/pageA/index.js", dependOn: "common" },
pageB: { import: "./src/pageB/index.js", dependOn: "common" },
common: ["./src/common/index.ts", "react", "react-dom", "lodash", "ahooks"]
}

4.3 场景

src/
├── main.js // 主入口文件
├── another.js // 另一个入口文件
└── shared.js // 共享模块
const path = require('path');

module.exports = {
entry: {
main: {
import: './src/main.js',
dependOn: 'shared', // main.js 依赖 shared.js
},
another: {
import: './src/another.js',
dependOn: 'shared', // another.js 也依赖 shared.js
},
shared: './src/shared.js', // 定义 shared.js 作为共享模块
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
};

打包结果

  • shared.bundle.js:包含 shared.js 的代码。

  • main.bundle.js:仅包含 main.js 的代码,但会依赖 shared.bundle.js

  • another.bundle.js:仅包含 another.js 的代码,同样依赖 shared.bundle.js

运行时

  • 加载 shared.bundle.js

  • 加载 main.bundle.jsanother.bundle.js

4.4 对于公共模块 common 是如何设计构建的?

小型项目或明确公共依赖时: 如果是小型项目或者项目公共依赖非常清晰(如所有页面都依赖 Reactlodashahooks),可以显式声明 common 入口。entry.common, 用于显式地声明哪些模块是所有页面共享的公共依赖, 通过 dependOn 配置,其他入口可以依赖 common,明确它与其他入口的依赖关系,从而避免重复打包。Webpack 在构建时会优先处理 common,减少每个入口的重复处理开销。entry.common 能够明确指定哪些文件属于公共模块,具有更高的控制力, 明确公共库的范围并提升构建速度。在多页面应用中,能避免遗漏重要的共享代码。但是,如果显式声明的 common 模块体积较小,可能会导致额外的网络请求,而合并到页面入口文件中反而更高效。而且每次新增或移除公共模块,都需要手动调整 entry.common。如果模块的共享逻辑复杂,可能导致配置难以维护。如下所示:

entry: {
common: ["react", "react-dom", "lodash", "ahooks"],
pageA: { import: "./src/pageA/index.js", dependOn: "common" },
pageB: { import: "./src/pageB/index.js", dependOn: "common" },
}

大型项目或动态依赖时: 如果是大型项目或者项目公共依赖复杂多样,我们无需显示声明 common, 我们可以直接使用 SplitChunks 提取所有 common 公共模块。splitChunks.cacheGroups.commonWebpack 的模块分割功能,通过自动分析和提取代码中的共享部分来优化打包结果。 它会自动根据配置,分析哪些模块是多入口或懒加载模块共享的,并提取到公共 chunksplitChunks 能够分割的不仅是 entry 声明的依赖,还包括动态导入(import())或异步加载的模块。通过 testpriority 和其他规则,可以对不同范围的模块分割细化控制。 如果模块分割策略设置得当,可以移除 common,完全依赖 SplitChunks, 并避免重复配置的潜在问题。如下所示:

optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
priority: 10,
},
common: {
test: /[\\/]src[\\/]common[\\/]/,
name: "common",
chunks: "all",
priority: 8,
reuseExistingChunk: true,
},
},
},
}

4.5 如果 entry 显示声明了 common 模块,而且在 SplitChunk 规则中也有,且有重叠,会发生什么呢?

entry.commonsplitChunks.cacheGroups.common 在功能上可能会存在重叠,具体情况取决于项目结构:

重叠场景: 如果 entry.commonsplitChunks.cacheGroups.common 的内容一致(如都包含 lodash),那么 splitChunks 的提取逻辑会将它们合并到一个 chunk 中,避免重复代码。这种情况下,entry.common 只是起到显式声明依赖关系的作用,而实际提取仍由 splitChunks 处理。

非重叠场景: 如果 entry.common 中的内容和 splitChunks.cacheGroups.common 提取的内容不同(如 entry.common 包含 lodash,而 splitChunks 提取的是共享组件),两者将生成各自的 chunk,不会相互影响。

五、asyncChunks


六、chunkLoading