在 webpack系列之多页面应用打包通用方案 一文中,介绍了多页面应用打包的实现方案。该方案借助 glob 模块拿到src目录下的多个入口文件,遍历后得到多个模板文件,最后将入口文件和模板文件都暴露出去,在 webpack.config.js 中使用。
在此文中,我们使用另外一种方案实现多页面应用管理。
AutoWebPlugin
AutoWebPlugin 是 web-webpack-plugin 插件的其中一个功能,它可以用来管理多个单页应用。是 html-webpack-plugin 的一个很好的替代品。
AutoWebPlugin 会找出一个目录下所有的目录,把每一个目录看成是一个单页应用,然后分别为每个单页应用生成一个 Chunk 配置和 WebPlugin 配置。即 AutoWebPlugin 支持所有 WebPlugin 支持的功能。
安装
npm i web-webpack-plugin --save-dev
引入 AutoWebPlugin
const { AutoWebPlugin } = require('web-webpack-plugin');
项目目录结构
例如一个项目的源码目录结构如下:
这也是 AutoWebPlugin 强制性规定的目录结构:
-
所有单页应用的代码都需要放在一个目录下,例如都放在 pages 目录下;
-
一个单页应用对应一个单独的文件夹,例如最后生成的 index.html 相关的源代码都在 index 目录下,list.html 和 login.html 同理
-
每个单页应用的目录下都有一个 index.js 文件作为入口文件
修改 webpack 配置
修改 webpack.config.js 文件如下:
const path = require('path');
// 导入 AutoWebPlugin
const { AutoWebPlugin } = require('web-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 使用 AutoWebPlugin 自动寻找 pages 目录下的所有目录,并把每一个目录看成是一个单页应用
const autoWebPlugin = new AutoWebPlugin('pages', {
template: './template.html', // HTML模板文件所在的文件路径
postEntrys:['./common.css'],// 所有的页面都依赖的共用的css样式文件
// 提取出所有页面的公共代码
commonsChunk: {
name: 'common'// 提取出公共代码的Chunk名称
}
});
module.exports = {
// AutoWebPlugin 会为寻找到的所有单页应用生成对应的入口配置
// autoWebPlugin.entry方法可以获取到所有由 autoWebPlugin 生成的入口配置
entry: autoWebPlugin.entry({
// 这里可以加入你额外需要的 chunk 入口
}),
output:{
filename: '[name]_[chunkhash:8].js',
path: path.resolve(__dirname, './dist'),
},
module: {
rules: [
{
test: /\.js$/,
use:['babel-loader'],
exclude: path.resolve(__dirname, 'node_modules'),
},
{
test: /\.css/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
autoWebPlugin,
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
}),
// ...
]
}
我们重点来看一下 AutoWebPlugin 的配置:
// 使用 AutoWebPlugin 自动寻找pages目录下的所有目录,把每一个目录看成是一个单页应用
const autoWebPlugin = new AutoWebPlugin('pages', {
template: './template.html', // HTML模板文件所在的文件路径
postEntrys:['./common.css'],// 所有的页面都依赖的共用的css样式文件
// 提取出所有页面的公共代码
commonsChunk: {
name: 'common'// 提取出公共代码的Chunk名称
}
});
在实例化 AutoWebPlugin 时,传入了一个 pages 参数和一个用于配置的对象。例如在上面的项目源码目录结构中,AutoWebPlugin 会自动寻找 pages 目录下的 index、list 和 login 目录,并把它们看成是三个单独的单页应用,并且分别为每个单页应用生成一个 Chunk 配置和 WebPlugin 配置。每个单页应用的 Chunk 名称就是文件夹的名称,也就是说 entry: autoWebPlugin.entry() 返回的最终内容是:
{
index:["./pages/index/index.js","./common.css"],
list: ["./pages/list/index.js", "./common.css"],
login:["./pages/login/index.js","./common.css"]
}
-
template:用于设置一个HTML模板文件。即 AutoWebPlugin 自动生成的HTML文件会以其为模板,在这个模板的基础上引入每个单页应用自身不同的CSS文件或者JS文件
template.html 模板文件:
<html>
<head>
<meta charset="UTF-8">
<!--该页面所依赖的其它剩下的 CSS 注入的地方-->
<!--STYLE-->
<!--注入 google_analytics 中的 JS 代码-->
<script src="./google_analytics.js?_inline"></script>
<!--异步加载 Disqus 评论-->
<script src="https://dive-into-webpack.disqus.com/embed.js" async></script>
</head>
<body>
<div id="app"></div>
<!--该页面所依赖的其它剩下的 JavaScript 注入的地方-->
<!--SCRIPT-->
<!--Disqus 评论容器-->
<div id="disqus_thread"></div>
</body>
</html>
打包后输出的 index.html:
<html>
<head>
<meta charset="UTF-8">
<!--该页面所依赖的其它剩下的 CSS 注入的地方-->
<link rel="stylesheet" href="common_7cc98ad0.css">
<link rel="stylesheet" href="index_04c08fbf.css">
<!--注入 google_analytics 中的 JS 代码-->
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');</script>
<!--异步加载 Disqus 评论-->
<script src="https://dive-into-webpack.disqus.com/embed.js" async=""></script>
</head>
<body>
<div id="app"></div>
<!--该页面所依赖的其它剩下的 JavaScript 注入的地方-->
<script src="common_39fd8e23.js"></script>
<script src="index_7f22d3cc.js"></script>
<!--Disqus 评论容器-->
<div id="disqus_thread"></div>
</body>
</html>
对比 template.html 和 index.html 文件,我们发现,template.html 中的 <!--STYLE--> 就是引入CSS文件的位置,<!--SCRIPT--> 就是引入JS文件的位置,AutoWebPlugin 会自动将页面依赖的资源按照不同的类型注入到 <!--STYLE--> 和 <!--SCRIPT--> 所在的位置。
-
postEntrys:用于设置所有页面都依赖的共用css文件
-
commonsChunk:用于提取所有页面的公共代码
输出结果
AutoWebPlugin 配置和其它的 webpack 配置已经配置好了,执行在 package.json 中配置的 build 命令 npm run build,在根目录下生成了一个 dist 文件夹,该文件夹里的文件就是通过 AutoWebPlugin 生成的多个单页应用的文件内容。
如果后续有新的页面需要开发,只需要在 pages 目录下新建一个目录,目录名称取为输出 HTML 文件的名称,目录下放这个页面相关的代码即可,无需改动构建代码。
项目代码地址:github.com/moozisheng/…