上一節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
插件還支持一些其它更高級的用法,詳情能夠訪問該項目主頁閱讀文檔。
本實例 提供項目完整代碼