配置项
一、layer
二、import
三、filename
四、dependOn
4.1 认识
entry.dependOn
是 Webpack entry
配置的一项功能,用于定义某个入口依赖于其他入口的共享模块。它通过显式声明入口间的依赖关系,优化打包效率,减少重复代码,并实现更精细的代码分割。 entry.dependOn
的作用如下:
-
减少重复代码: 当多个入口共享相同的依赖时,
dependOn
可以将这些依赖提取到一个单独的共享文件中。 -
优化打包: 避免在多个入口的打包文件中重复引入相同的依赖,提升构建速度和加载效率。
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.j
s:仅包含another.js
的代码,同样依赖shared.bundle.js
。
运行时:
-
加载
shared.bundle.js
。 -
加载
main.bundle.js
或another.bundle.js
。
4.4 对于公共模块 common 是如何设计构建的?
小型项目或明确公共依赖时: 如果是小型项目或者项目公共依赖非常清晰(如所有页面都依赖 React
、lodash
、ahooks
),可以显式声明 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.common
是 Webpack
的模块分割功能,通过自动分析和提取代码中的共享部分来优化打包结果。 它会自动根据配置,分析哪些模块是多入口或懒加载模块共享的,并提取到公共 chunk
。 splitChunks
能够分割的不仅是 entry
声明的依赖,还包括动态导入(import()
)或异步加载的模块。通过 test
、priority
和其他规则,可以对不同范围的模块分割细化控制。 如果模块分割策略设置得当,可以移除 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.common
和 splitChunks.cacheGroups.common
在功能上可能会存在重叠,具体情况取决于项目结构:
重叠场景: 如果 entry.common
和 splitChunks.cacheGroups.common
的内容一致(如都包含 lodash
),那么 splitChunks
的提取逻辑会将它们合并到一个 chunk
中,避免重复代码。这种情况下,entry.common
只是起到显式声明依赖关系的作用,而实际提取仍由 splitChunks
处理。
非重叠场景: 如果 entry.common
中的内容和 splitChunks.cacheGroups.common
提取的内容不同(如 entry.common
包含 lodash
,而 splitChunks
提取的是共享组件),两者将生成各自的 chunk
,不会相互影响。