在日常的vue和react的开发中可能比较少出现这种多入口和不同入口对应不同入口文件的情况
最近在玩electron的时候对打包的一些问题发现比较陌生,特此出一篇文章来记录一下webpack的一些实践,本文主要是对于上一篇文章的electron打开新窗口出现两个入口并且两个入口都加载同一个入口的js文件为基础,在上文中说道
dialog.html和index.html都会加载同一个renderer.dev.js
这可能是需要在webpack中做一些配置来进行解决
HtmlWebpackPlugin 配置及其作用
由于我们在electron中新建一个窗口,所以也就是需要有两个入口,用HtmlWebpackPlugin来生成另外一个入口。目前会有两个入口一个是index.html,另外是dialog.html
js
//const srcRendererPath = path.join(srcPath, 'renderer');这是路径
new HtmlWebpackPlugin({
filename: path.join('index.html'),
template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
isBrowser: false,
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
}),
new HtmlWebpackPlugin({
filename: path.join('dialog.html'),
template: path.join(webpackPaths.srcRendererPath, 'components/index.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
isBrowser: false,
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
}),
自动生成 HTML 文件
HtmlWebpackPlugin
会根据提供的配置和模板,在输出目录中自动生成 HTML 文件。
js
//index.ejs 模版ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline'"
/>
<title>Electron</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
自动输出资源
HtmlWebpackPlugin
会自动将生成的打包后的 JavaScript 和 CSS 文件注入到生成的 HTML 文件中,确保正确的引入路径。
htmlwebpackplugin会根据模版和路径进行打包,这是打包后生成的文件
生成的index.html入口文件
我们可以看到打包生成的html中会自动带上js和css,所以我们要找到哪里的配置是对应生成这部分内容的,啥也不懂没关系,我们直接全局搜renderer,我觉得这是一个比较简单的方法,要想知道某个文件的来源和生成,直接在配置中搜可以解决百分之90的问题。
打包后的index.html会引入renderer.js 也是webpack配置引起的
js
output: {
path: webpackPaths.distRendererPath,
publicPath: '/',
filename: 'renderer.dev.js',
library: {
type: 'umd',
},
},
output
: 这是打包后输出文件的配置选项。
a. path
: 这是输出文件的根目录路径。webpackPaths.distRendererPath
是指定的路径
b. publicPath
: 这是指定打包后文件的发布路径。在此配置中,将其设置为根目录 /
,这意味着生成的文件将在根目录下,例如 http://localhost:port/renderer.dev.js
。
c. filename
: 这是生成的输出文件的名称,即 renderer.dev.js
。
由于output的配置,所以我们的入口文件,也就是上文引入的html,会被自动引入output的js,这也就是为什么我们在index.html和dialog.html中都会加载rederer.dev.js的原因,因为index和dialog是我们声明的两个入口。
不同入口配置不同输出文件
对于有两个入口文件的情况,需要为每个入口文件配置不同的 output
。可以通过使用 [name]
占位符来生成多个输出文件
js
entry: {
index: [
`webpack-dev-server/client?http://localhost:${port}/dist`,
'webpack/hot/only-dev-server',
path.join(webpackPaths.srcRendererPath, 'index.tsx'),
],
dialog: [
`webpack-dev-server/client?http://localhost:${port}/dist`,
'webpack/hot/only-dev-server',
path.join(webpackPaths.srcRendererPath, 'components/index.tsx'),
],
},
output: {
path: webpackPaths.distRendererPath,
publicPath: '/',
filename: '[name].renderer.dev.js',
library: {
type: 'umd',
},
},
entry
: 是指定应用程序的入口点的地方
index
: 这是应用程序的主要入口点。它包含在path.join(webpackPaths.srcRendererPath, 'index.tsx')
文件中dialog
: 这是另一个入口点,包含在path.join(webpackPaths.srcRendererPath, 'components/index.tsx')
文件中
output.filename
: 这是生成的输出文件的名称,即 [name].renderer.dev.js
。在这里,[name]
将根据入口文件的名称自动替换为 'index' 或 'dialog'。
output
中的 [name]
部分是与 entry
中的入口名称相对应的占位符。当 Webpack 打包这些入口文件时,它会根据每个入口文件的名称生成对应的输出文件,之后会生成index.renderer.js和dialog.renderer.js
配置加载输出文件
根据上面的配置,可能还会出现一个问题,就是在一个入口html中会引入两个js,所以需要再改一下配置
我们可以将每个 HtmlWebpackPlugin 实例的 chunks
属性设置为仅包含对应的入口名称。这样,每个 HTML 文件只会引入与其对应的入口 JS 文件。
js
new HtmlWebpackPlugin({
filename: path.join('dialog.html'),
template: path.join(webpackPaths.srcRendererPath, 'components/index.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
chunks: ['dialog'], // 仅引入对应的入口文件
isBrowser: false,
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
}),
new HtmlWebpackPlugin({
filename: path.join('index.html'),
chunks: ['index'], // 仅引入对应的入口文件
template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
},
isBrowser: false,
env: process.env.NODE_ENV,
isDevelopment: process.env.NODE_ENV !== 'production',
nodeModules: webpackPaths.appNodeModulesPath,
}),
最后结果
最后通过打开不同的窗口加载不同的index和dialog入口,会分别加载入口文件。
js
//main.js
mainWindow.loadURL(resolveHtmlPath('index.html'));
dialogWindow.loadURL(resolveHtmlPath('dialog.html'));