我如何在 Webpack 中使用多个条目以及 HtmlWebpackPlugin 中的多个 HTML 文件?
How can I use multiple entries in Webpack alongside multiple HTML files in HtmlWebpackPlugin?
我们希望 Webpack 有两个输出——我们的整个应用程序及其所有依赖项,以及一个单独的不同页面,只有一个依赖项(主应用程序不共享)。
看起来这样做的方法是利用 Webpack 配置的 entry
属性。然而,这还不够,因为我们还使用 HtmlWebpackPlugin 输出我们的 HTML 文件,其中 build.js
是 Webpack 编译动态添加的(以及编译的 LESS 等)。根据 HtmlWebpackPlugin 文档:
If you have multiple Webpack entry points, they will all be included
with script tags in the generated HTML.
这对我们不起作用,所以我需要利用他们的 filterChunks
选项。这个 GitHub issue response 最简洁地说明了这一点:
module.exports = {
entry: {
'page1': './apps/page1/scripts/main.js',
'page2': './apps/page2/src/main.js'
},
output: {
path: __dirname,
filename: "apps/[name]/build/bundle.js"
},
plugins: [
new HtmlWebpackPlugin({
inject: false,
chunks: ['page1'],
filename: 'apps/page1/build/index.html'
}),
new HtmlWebpackPlugin({
inject: false,
chunks: ['page2'],
filename: 'apps/page2/build/index.html'
})
]
};
(在 HtmlWebpackPlugin 文档中,这是在 "filtering chunks" 部分下)
所以,我修改了我们的代码:
module.exports = {
entry: {
app: './public/js/ide.js',
resetPassword: './public/js/reset_password.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: '/'
},
...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'reset_password.html',
template: 'public/html/reset_password.html',
inject: true,
chunks: ['resetPassword']
}),
],
}
现在,当我重建项目(现在只是尝试使用 WebpackDevServer)并导航到 /index.html
时,我可以在网络选项卡中看到大量的捆绑文件,index.html
的内容(基于 ide.html
模板),以及对各种外部资源的请求。但是,没有实际的 JavaScript 会 运行(例如,ide.js
中的 console.log)。文件中的所有 HTML 显示。
对于reset_password.html
,所有HTML显示,reset_password.js
文件显示,但运行s内的javascript的none .
如何确保我的 entry
文件 运行 中的 JavaScript?
编辑:我已经ide.js
工作了,因为我没有意识到以下是"chunk":
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\/]node_modules[\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
因此,我将 vendor
添加到 index.html
HtmlWebpackPlugin chunks
属性。现在,它看起来像这样:
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app', 'vendor']
}),
reset_password
不需要 node_modules 文件夹中的任何内容,这也不能解释为什么根本没有 JavaScript 会 运行 在 ide.js
,所以我还是很困惑。此外,reset_password
仍然无法正常工作。
EDIT2:当我加载 reset_password.html
时查看明显附加的 reset_password.js
文件,我可以看到这一行
eval("\n\nconsole.log('DRAGONHELLO');//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9wdWJsaWMvanMvcmVzZXRfcGFzc3dvcmQuanM/ZjY5ZSJdLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiOztBQUNBQSxRQUFRQyxHQUFSLENBQVksYUFBWiIsImZpbGUiOiIuL3B1YmxpYy9qcy9yZXNldF9wYXNzd29yZC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc29sZS5sb2coJ0RSQUdPTkhFTExPJylcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./public/js/reset_password.js\n");
所以,显然我的 console.log('DRAGONHELLO')
是 "seen",但我不知道为什么它不是 运行ning。
EDIT3:为 reset_password.html
添加 vendor
到 chunks
导致 JavaScript 到 运行,但是我不知道为什么,这是不理想的,因为整个练习的重点是有两个不同的包,一个非常小,不需要我们所有的 node_modules
。
EDIT4:我使用 运行 Webpack profile:true
,我可以看到我没有弄错 "Chunk Names":
js/app.3d18b43294ebd54ed083.js 1.34 MiB 0 [emitted] [big] app
js/resetPassword.198485be2b163cc258ed.js 1.02 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js 2.23 MiB 2 [emitted] [big] vendor
js/app.3d18b43294ebd54ed083.js.map 2.71 MiB 0 [emitted] app
js/resetPassword.198485be2b163cc258ed.js.map 4.57 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js.map 7.12 MiB 2 [emitted] vendor
EDIT5:我都试过了
module.exports = {
//...
optimization: {
runtimeChunk: {
name: entrypoint => `runtime~${entrypoint.name}`
}
}
};
和
module.exports = {
//...
optimization: {
runtimeChunk: true
}
};
基于 PlayMa256 的评论和 webpack docs on runtimeChunk。两者都没有导致 JavaScript 执行。
设置时:
module.exports = {
//...
optimization: {
runtimeChunk: true
}
};
它生成一个运行时间块。 运行时间是什么?运行时是 webpack 用来加载其他文件的所有代码所在的地方。当您 运行 构建时,这是 webpack 的核心。
因为您有 2 个单独的捆绑文件:resetPassword
和 app
。
好的,您拥有所需的所有文件。您可能也需要供应商,因为您的供应商包含 node_modules 中的所有内容。所以基本上你会有:
html 1: app
, vendor
, runtimeChunk
.
html 2: reset_password
, vendor
, runtimeChunk
.
通过这样做,您的应用程序应该 运行。
这是一个多部分问题。
首先,there is a bug in Html-Webpack-Plugin that makes it incompatible with Webpack4 and multiple entrypoints. It must be upgraded to v4.0.0-alpha.2至少要工作。
其次,在新版本中,您无需使用optimization.splitChunks.cacheGroups
手动分离出node_modules。执行 optimization.splitChunks.chunks = 'all'
足以导致给定的入口点仅进入其 vendors-app-{{chunk_name}}
块 node_modules 它实际上是 import
s。
所以如果你这样做
optimization: {
splitChunks: {
chunks: 'all'
},
},
结合
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'reset_password.html',
template: 'public/html/reset_password.html',
inject: true,
chunks: ['resetPassword']
}),
]
结合
entry: {
app: './public/js/ide.js',
resetPassword: './public/js/reset_password.js'
},
然后,你的 webpack 输出将有
- 应用
- 重置密码
- 供应商~应用~重置密码
- 供应商~应用程序
- 供应商~重置密码
除非你的 resetPassword.js
文件中没有 imports
,在这种情况下它看起来像
- 应用
- 重置密码
- vendors~app~resetPassword(必要的webpack供应商包)
- 供应商~应用程序
更多信息、图像和对话,请访问 https://github.com/jantimon/html-webpack-plugin/issues/1053
请注意,对于最新版本,chunksSortMode:
不再是 HtmlWebpackPlugin 对象上的有效选项,它显然在 webpack4 中默认完成。
我们希望 Webpack 有两个输出——我们的整个应用程序及其所有依赖项,以及一个单独的不同页面,只有一个依赖项(主应用程序不共享)。
看起来这样做的方法是利用 Webpack 配置的 entry
属性。然而,这还不够,因为我们还使用 HtmlWebpackPlugin 输出我们的 HTML 文件,其中 build.js
是 Webpack 编译动态添加的(以及编译的 LESS 等)。根据 HtmlWebpackPlugin 文档:
If you have multiple Webpack entry points, they will all be included with script tags in the generated HTML.
这对我们不起作用,所以我需要利用他们的 filterChunks
选项。这个 GitHub issue response 最简洁地说明了这一点:
module.exports = {
entry: {
'page1': './apps/page1/scripts/main.js',
'page2': './apps/page2/src/main.js'
},
output: {
path: __dirname,
filename: "apps/[name]/build/bundle.js"
},
plugins: [
new HtmlWebpackPlugin({
inject: false,
chunks: ['page1'],
filename: 'apps/page1/build/index.html'
}),
new HtmlWebpackPlugin({
inject: false,
chunks: ['page2'],
filename: 'apps/page2/build/index.html'
})
]
};
(在 HtmlWebpackPlugin 文档中,这是在 "filtering chunks" 部分下)
所以,我修改了我们的代码:
module.exports = {
entry: {
app: './public/js/ide.js',
resetPassword: './public/js/reset_password.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: '/'
},
...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'reset_password.html',
template: 'public/html/reset_password.html',
inject: true,
chunks: ['resetPassword']
}),
],
}
现在,当我重建项目(现在只是尝试使用 WebpackDevServer)并导航到 /index.html
时,我可以在网络选项卡中看到大量的捆绑文件,index.html
的内容(基于 ide.html
模板),以及对各种外部资源的请求。但是,没有实际的 JavaScript 会 运行(例如,ide.js
中的 console.log)。文件中的所有 HTML 显示。
对于reset_password.html
,所有HTML显示,reset_password.js
文件显示,但运行s内的javascript的none .
如何确保我的 entry
文件 运行 中的 JavaScript?
编辑:我已经ide.js
工作了,因为我没有意识到以下是"chunk":
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\/]node_modules[\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
因此,我将 vendor
添加到 index.html
HtmlWebpackPlugin chunks
属性。现在,它看起来像这样:
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app', 'vendor']
}),
reset_password
不需要 node_modules 文件夹中的任何内容,这也不能解释为什么根本没有 JavaScript 会 运行 在 ide.js
,所以我还是很困惑。此外,reset_password
仍然无法正常工作。
EDIT2:当我加载 reset_password.html
时查看明显附加的 reset_password.js
文件,我可以看到这一行
eval("\n\nconsole.log('DRAGONHELLO');//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9wdWJsaWMvanMvcmVzZXRfcGFzc3dvcmQuanM/ZjY5ZSJdLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiOztBQUNBQSxRQUFRQyxHQUFSLENBQVksYUFBWiIsImZpbGUiOiIuL3B1YmxpYy9qcy9yZXNldF9wYXNzd29yZC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc29sZS5sb2coJ0RSQUdPTkhFTExPJylcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./public/js/reset_password.js\n");
所以,显然我的 console.log('DRAGONHELLO')
是 "seen",但我不知道为什么它不是 运行ning。
EDIT3:为 reset_password.html
添加 vendor
到 chunks
导致 JavaScript 到 运行,但是我不知道为什么,这是不理想的,因为整个练习的重点是有两个不同的包,一个非常小,不需要我们所有的 node_modules
。
EDIT4:我使用 运行 Webpack profile:true
,我可以看到我没有弄错 "Chunk Names":
js/app.3d18b43294ebd54ed083.js 1.34 MiB 0 [emitted] [big] app
js/resetPassword.198485be2b163cc258ed.js 1.02 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js 2.23 MiB 2 [emitted] [big] vendor
js/app.3d18b43294ebd54ed083.js.map 2.71 MiB 0 [emitted] app
js/resetPassword.198485be2b163cc258ed.js.map 4.57 KiB 1 [emitted] resetPassword
js/2.e7f92193ea3c611a0b36.js.map 7.12 MiB 2 [emitted] vendor
EDIT5:我都试过了
module.exports = {
//...
optimization: {
runtimeChunk: {
name: entrypoint => `runtime~${entrypoint.name}`
}
}
};
和
module.exports = {
//...
optimization: {
runtimeChunk: true
}
};
基于 PlayMa256 的评论和 webpack docs on runtimeChunk。两者都没有导致 JavaScript 执行。
设置时:
module.exports = {
//...
optimization: {
runtimeChunk: true
}
};
它生成一个运行时间块。 运行时间是什么?运行时是 webpack 用来加载其他文件的所有代码所在的地方。当您 运行 构建时,这是 webpack 的核心。
因为您有 2 个单独的捆绑文件:resetPassword
和 app
。
好的,您拥有所需的所有文件。您可能也需要供应商,因为您的供应商包含 node_modules 中的所有内容。所以基本上你会有:
html 1: app
, vendor
, runtimeChunk
.
html 2: reset_password
, vendor
, runtimeChunk
.
通过这样做,您的应用程序应该 运行。
这是一个多部分问题。
首先,there is a bug in Html-Webpack-Plugin that makes it incompatible with Webpack4 and multiple entrypoints. It must be upgraded to v4.0.0-alpha.2至少要工作。
其次,在新版本中,您无需使用optimization.splitChunks.cacheGroups
手动分离出node_modules。执行 optimization.splitChunks.chunks = 'all'
足以导致给定的入口点仅进入其 vendors-app-{{chunk_name}}
块 node_modules 它实际上是 import
s。
所以如果你这样做
optimization: {
splitChunks: {
chunks: 'all'
},
},
结合
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/html/ide.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'reset_password.html',
template: 'public/html/reset_password.html',
inject: true,
chunks: ['resetPassword']
}),
]
结合
entry: {
app: './public/js/ide.js',
resetPassword: './public/js/reset_password.js'
},
然后,你的 webpack 输出将有
- 应用
- 重置密码
- 供应商~应用~重置密码
- 供应商~应用程序
- 供应商~重置密码
除非你的 resetPassword.js
文件中没有 imports
,在这种情况下它看起来像
- 应用
- 重置密码
- vendors~app~resetPassword(必要的webpack供应商包)
- 供应商~应用程序
更多信息、图像和对话,请访问 https://github.com/jantimon/html-webpack-plugin/issues/1053
请注意,对于最新版本,chunksSortMode:
不再是 HtmlWebpackPlugin 对象上的有效选项,它显然在 webpack4 中默认完成。