在开始前先来看看该应用最终发布到线上的代码。
See the Pen 管理多个单页应用 by whjin (@whjin) on CodePen.
构建出的目录结构为:
dist
├── common_029086ff.js
├── common_7cc98ad0.css
├── index.html
├── index_04c08fbf.css
├── index_b3d3761c.js
├── login.html
├── login_0a3feca9.js
└── login_e31e214b.css
如果按照上节的思路,可能需要为每个单页应用配置一段如下代码:
new WebPlugin({
template: './template.html', // HTML 模版文件所在的文件路径
filename: 'login.html' // 输出的 HTML 的文件名称
})
并且把页面对应的入口加入到 enrty
配置项中,就像这样:
entry: {
index: './pages/index/index.js',// 页面 index.html 的入口文件
login: './pages/login/index.js',// 页面 login.html 的入口文件
}
当有新页面加入时就需要修改 Webpack 配置文件,新插入一段以上代码,这会导致构建代码难以维护而且易错。
项目源码目录结构如下:
├── pages
│ ├── index
│ │ ├── index.css // 该页面单独需要的 CSS 样式
│ │ └── index.js // 该页面的入口文件
│ └── login
│ ├── index.css
│ └── index.js
├── common.css // 所有页面都需要的公共 CSS 样式
├── google_analytics.js
├── template.html
└── webpack.config.js
从目录结构中可以看成出下几点要求:
pages
目录下;index.html
相关的代码都在 index
目录下,login.html
同理;index.js
文件作为入口执行文件。虽然
AutoWebPlugin
强制性的规定了项目部分的目录结构,但从实战经验来看这是一种优雅的目录规范,合理的拆分了代码,又能让新人快速的看懂项目结构,也方便日后的维护。
Webpack 配置文件修改如下:
See the Pen webpack管理多个单页应用 by whjin (@whjin) on CodePen.
AutoWebPlugin
会找出 pages
目录下的2个文件夹 index
和 login
,把这两个文件夹看成两个单页应用。 并且分别为每个单页应用生成一个 Chunk 配置和 WebPlugin 配置。 每个单页应用的 Chunk 名称就等于文件夹的名称,也就是说 autoWebPlugin.entry()
方法返回的内容其实是:
{
"index":["./pages/index/index.js","./common.css"],
"login":["./pages/login/index.js","./common.css"]
}
但这些事情 AutoWebPlugin
都会自动为你完成,你不用操心,明白大致原理即可。
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>
由于这个模版文件被当作项目中所有单页应用的模版,就不能再像上一节中直接写 Chunk 的名称去引入资源,因为需要被注入到当前页面的 Chunk 名称是不定的,每个单页应用都会有自己的名称。 <!--STYLE-->
和 <!--SCRIPT-->
的作用在于保证该页面所依赖的资源都会被注入到生成的 HTML 模版里去。
web-webpack-plugin
能分析出每个页面依赖哪些资源,例如对于 login.html
来说,插件可以确定该页面依赖以下资源:
common.css
;common.js
;login.css
;login.css
。由于模版文件 template.html
里没有指出引入这些依赖资源的 HTML 语句,插件会自动将没有手动导入但页面依赖的资源按照不同类型注入到 <!--STYLE-->
和 <!--SCRIPT-->
所在的位置。
<!--STYLE-->
所在的位置,如果 <!--STYLE-->
不存在就注入到 HTML HEAD 标签的最后;<!--SCRIPT-->
所在的位置,如果 <!--SCRIPT-->
不存在就注入到 HTML BODY 标签的最后。如果后续有新的页面需要开发,只需要在 pages
目录下新建一个目录,目录名称取为输出 HTML 文件的名称,目录下放这个页面相关的代码即可,无需改动构建代码。
由于 AutoWebPlugin
是间接的通过上一节提到的 WebPlugin
实现的,WebPlugin
支持的功能 AutoWebPlugin
都支持。