上一节3-9为单页应用生成HTML中只生成了一个 HTML 文件,但在实际应用中一个完整的系统不会把全部的功能都作到一个网页中,由于这会致使这个网页性能不佳。
实际的作法是按照功能模块划分红多个单页应用,每一个单页应用生成一个 HTML 文件。而且随着业务的发展更多的单页应用可能会逐渐被加入到项目中去。css
虽然上一节已经解决了自动化生成 HTML 的痛点,可是手动去管理多个单页应用的生成也是一件麻烦的事情。
来继续改造上一节的例子,要求以下:html
index.html
,一个是用户登入页 login.html
;在开始前先来看看该应用最终发布到线上的代码。webpack
login.html
文件内容:git
<html> <head> <meta charset="UTF-8"> <!--从多个页面中抽离出的公共 CSS 代码--> <link rel="stylesheet" href="common_7cc98ad0.css"> <!--只有这个页面须要的 CSS 代码--> <link rel="stylesheet" href="login_e31e214b.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 async="" src="https://dive-into-webpack.disqus.com/embed.js"></script> </head> <body> <div id="app"></div> <!--从多个页面中抽离出的公共 JavaScript 代码--> <script src="common_a1d9142f.js"></script> <!--只有这个页面须要的 JavaScript 代码--> <script src="login_f926c4e6.js"></script> <!--Disqus 评论容器--> <div id="disqus_thread"></div> </body> </html>
构建出的目录结构为:github
dist ├── common_029086ff.js ├── common_7cc98ad0.css ├── index.html ├── index_04c08fbf.css ├── index_b3d3761c.js ├── login.html ├── login_0a3feca9.js └── login_e31e214b.css
若是按照上节的思路,可能须要为每一个单页应用配置一段以下代码:web
new WebPlugin({ template: './template.html', // HTML 模版文件所在的文件路径 filename: 'login.html' // 输出的 HTML 的文件名称 })
而且把页面对应的入口加入到 enrty
配置项中,就像这样:json
entry: { index: './pages/index/index.js',// 页面 index.html 的入口文件 login: './pages/login/index.js',// 页面 login.html 的入口文件 }
当有新页面加入时就须要修改 Webpack 配置文件,新插入一段以上代码,这会致使构建代码难以维护并且易错。app
上一节中的 web-webpack-plugin 插件也内置了解决这个问题的方法,上一节中只使用了它的 WebPlugin
,
这节将使用它的 AutoWebPlugin
来解决以上问题,使用方法很是简单,下面来教你具体如何使用。框架
项目源码目录结构以下:异步
├── pages │ ├── index │ │ ├── index.css // 该页面单独须要的 CSS 样式 │ │ └── index.js // 该页面的入口文件 │ └── login │ ├── index.css │ └── index.js ├── common.css // 全部页面都须要的公共 CSS 样式 ├── google_analytics.js ├── template.html └── webpack.config.js
从目录结构中能够当作出下几点要求:
index.html
相关的代码都在 index
目录下,login.html
同理;index.js
文件做为入口执行文件。
虽然
AutoWebPlugin
强制性的规定了项目部分的目录结构,但从实战经验来看这是一种优雅的目录规范,合理的拆分了代码,又能让新人快速的看懂项目结构,也方便往后的维护。
Webpack 配置文件修改以下:
const { AutoWebPlugin } = require('web-webpack-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 入口 }), plugins: [ autoWebPlugin, ], };
以上配置文件为了重点展现出本文侧重修改的部分,省略了部分和上一节一致的代码,完整代码能够参照上一节或者下载本项目完整代码。
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>
注意到模版文件中出现了2个重要的新关键字 <!--STYLE-->
和 <!--SCRIPT-->
,它们是什么意思呢?
因为这个模版文件被看成项目中全部单页应用的模版,就不能再像上一节中直接写 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
都支持。
AutoWebPlugin
插件还支持一些其它更高级的用法,详情能够访问该项目主页阅读文档。
本实例 提供项目完整代码