入口点(Entry)
入口点(Entry)
在起步指南中提到过,webpack 配置中的 entry 属性有多种定义方式。本文将展示这些配置方式,并解释每种方式的使用场景。
简单来说,入口点(entry point)告诉 webpack 从哪里开始构建内部依赖图。webpack 会从这个文件出发,递归地追踪所有被导入的模块和资源,以此决定最终打包产物中应包含哪些内容。
这一过程的结果随后会根据 output 配置写入磁盘,output 决定了打包文件的输出位置和方式。
T> 当运行 webpack 而未提供配置文件时,entry 默认为 './src/index.js'。如果该文件不存在——即使 src/ 目录存在——webpack 也会抛出以下错误:
ERROR in Entry module not found: Error: Can't resolve './src'
错误信息中显示的是 './src' 而非 './src/index.js',这是因为 webpack 会先解析目录,然后在目录中查找 index.js。若要使用其他入口文件名,请按下文各节所示配置 entry 选项。
单个入口(简写)语法
用法:entry: string | [string]
string:单个入口文件[string]:多个入口文件
webpack.config.js
js
export default {
entry: "./path/to/my/entry/file.js",
};
entry 属性的单个入口语法等价于:
webpack.config.js
js
export default {
entry: {
main: "./path/to/my/entry/file.js",
},
};
我们也可以向 entry 属性传入一个文件路径数组,这将创建所谓的 "多主入口"(multi-main entry)。当你希望将多个相互依赖的文件合并在一起,并将它们的依赖关系整合到同一个 "chunk" 中时,这种写法非常有用。
webpack.config.js
js
export default {
entry: ["./src/file_1.js", "./src/file_2.js"],
};
当入口点传入数组时,webpack 仍然只会创建一个单个入口 chunk。数组中的所有模块都会按给定顺序加载,并合并到同一个依赖图中。
这种模式常用于在主应用入口之前注入额外代码,例如 polyfill 或仅开发环境使用的工具,而无需在应用源码中手动引入它们。
示例:注入 polyfill
js
export default {
entry: {
main: ["@babel/polyfill", "./src/index.js"],
},
};
当你希望为只有一个入口点的应用或工具(例如库)快速搭建 webpack 配置时,单个入口语法是一个很好的选择。但这种语法在扩展和规模化配置方面的灵活性有限。
对象语法
用法:entry: { <entryChunkName> string | [string] } | {}
<entryChunkName>:入口 chunk 的名称string:单个入口文件[string]:多个入口文件{}:空对象
webpack.config.js
js
export default {
entry: {
app: "./src/app.js",
adminApp: "./src/adminApp.js",
},
};
对象语法虽然更冗长,但它是在应用中定义入口/多个入口时最具扩展性的方式。
T> **"可扩展的 webpack 配置"**是指能够被复用并与其他部分配置合并的配置。这是一种流行的技术,用于按环境、构建目标和运行时来分离关注点,然后借助 webpack-merge 等专用工具进行合并。
T> 当只有由插件生成的入口点时,可以向 entry 传入空对象 {}。
EntryDescription 对象
这是一个描述入口点的对象,可以指定以下属性:
dependOn:当前入口点所依赖的其他入口点。在加载当前入口点之前,这些依赖项必须已加载完成。filename:指定每个输出文件在磁盘上的名称。import:启动时需要加载的模块。library:指定 library 选项,以便从当前入口打包一个库。runtime:运行时 chunk 的名称。设置后会创建一个新的运行时 chunk。自 webpack 5.43.0 起,可将其设置为false以避免创建新的运行时 chunk。publicPath:当浏览器引用此入口的输出文件时,指定一个公共 URL 地址。另请参阅 output.publicPath。
webpack.config.js
js
export default {
entry: {
a2: "dependingfile.js",
b2: {
dependOn: "a2",
import: "./src/app.js",
},
},
};
在单个入口上,runtime 和 dependOn 不能同时使用。因此以下配置无效并会抛出错误:
webpack.config.js
js
export default {
entry: {
a2: "./a",
b2: {
runtime: "x2",
dependOn: "a2",
import: "./b",
},
},
};
确保 runtime 不能指向已存在的入口点名称,例如以下配置会抛出错误:
js
export default {
entry: {
a1: "./a",
b1: {
runtime: "a1",
import: "./b",
},
},
};
同样,dependOn 不能形成循环依赖,以下示例同样会抛出错误:
js
export default {
entry: {
a3: {
import: "./a",
dependOn: "b3",
},
b3: {
import: "./b",
dependOn: "a3",
},
},
};
场景示例
下面列出了一些入口配置及其实际应用场景:
分离应用与第三方库入口
webpack.config.js
js
export default {
entry: {
main: "./src/app.js",
vendor: "./src/vendor.js",
},
};
在 production 模式下构建时:
webpack.prod.js
js
export default {
output: {
filename: "[name].[contenthash].bundle.js", // 例如:main.abc123.bundle.js、vendor.abc123.bundle.js
},
};
在 development 模式下构建时:
webpack.dev.js
js
export default {
output: {
filename: "[name].bundle.js", // 例如:main.bundle.js、vendor.bundle.js
},
};
这样做有什么效果? 我们是在告诉 webpack 需要两个独立的入口点(如上例所示)。
为什么? 通过这种方式,你可以将不会改动的库或文件(例如 Bootstrap、jQuery、图片等)引入 vendor.js,让它们打包到独立的 chunk 中。content hash 保持不变,浏览器可以单独缓存它们,从而减少加载时间。
T> 在 webpack 4 之前的版本中,通常会将第三方库作为单独的入口点来编译成独立文件(配合 CommonsChunkPlugin 使用)。
但在 webpack 4 中不推荐这样做。取而代之的是,optimization.splitChunks 选项负责分离第三方库和应用模块,并创建独立文件。不要为第三方库或其他并非执行起点的内容创建入口。
多页面应用
webpack.config.js
js
export default {
entry: {
pageOne: "./src/pageOne/index.js",
pageTwo: "./src/pageTwo/index.js",
pageThree: "./src/pageThree/index.js",
},
};
这样做有什么效果? 我们是在告诉 webpack 需要 3 个独立的依赖图(如上例所示)。
为什么? 在多页面应用中,服务器会为每次页面导航返回一个新的 HTML 文档。页面加载新文档时,所有资源都会被重新下载。但这给了我们独特的机会,例如使用 optimization.splitChunks 在每个页面之间创建共享应用代码的 bundle。当入口点数量增加时,在不同入口点之间大量复用代码/模块的多页面应用可以从中大大受益。
T> 经验法则:每个 HTML 文档只使用一个入口点。更多细节请参阅此处描述的问题。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
