在事件專案中,一個頁面常常有很多資源要載入,舉出一個實戰中的例子要求如下:
- 專案採用ES6語言加react框架;
- 給頁面假如google analytics, 這部分程式碼需要內嵌進head標籤裡去。
- 給頁面假如Disqus使用者評論, 這部分程式碼需要非同步載入以提升首屏載入速度。
- 壓縮和分類JavaScript和css程式碼,提升載入速度。
以下是釋出到線上的程式碼 :
<html>
<head>
<meta charset="UTF-8">
<!--注入 Chunk app 依賴的 CSS-->
<style rel="stylesheet">h1{color:red}</style>
<!--內嵌 google_analytics 中的 JavaScript 程式碼-->
<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>
<!--匯入 app 依賴的 JS-->
<script src="app_746f32b2.js"></script>
<!--Disqus 評論容器-->
<div id="disqus_thread"></div>
</body>
</html>
構建出的目錄結構為:
dist
├── app_792b446e.js
└── index.html
可以看到部分程式碼被內嵌進入了HTML的head標籤中,部分檔案的檔名稱被打上根據檔案內容算出的Hash值,並且載入這些檔案的URL地址也被正常的注入到了HTML中。如果還是手寫HTML檔案去完成以上要求,這就會使工作變得複雜、易錯、專案難以維護。
解決方案
推薦一個用於方便的解決以上為的webpack外掛web-webpack-plugin。
首先,修改webpack配置:
const path = require(`path`);
const UglifyJsPlugin = require(`webpack/lib/optimize/UglifyJsPlugin`);
const ExtractTextPlugin = require(`extract-text-webpack-plugin`);
const DefinePlugin = require(`webpack/lib/DefinePlugin`);
const { WebPlugin } = require(`web-webpack-plugin`);
module.exports = {
entry: {
app: `./main.js` //app的js入口檔案
},
output: {
filename: `[name]_[chunkhash:8].js`給輸出的檔案加上hash值
path: path.resolve(__dirname, `./dist`)
},
module: {
rules: [
{
test: /.js$/,
use: [`babel-loader`],
//排除node_modules目錄下的檔案
//該目錄下的檔案都是ES5語法,沒必要再通過babel去轉換
exclude: path.resolve(__dirname, "node_modules")
},
{
test: /.css/, //增加對css檔案的支援
//提取出chunk中的css程式碼到單獨的檔案中
use: ExtractTextPlugin.extract({
use: ["css-loader?minimize"] //壓縮css程式碼
})
}
]
},
plugins: [
//使用本文的主角WebPlugin,一個WebPlugin對應一個HTML檔案
new WebPlugin({
template: "./template.html", //HTML模板檔案所在的檔案路徑
filename: "index.html" //輸出HTML的檔名稱
}),
new ExtractTextPlugin({
filename: `[name]_[contenthash:8].css`,//給輸出的css檔名稱加上hash值
}),
new DefinePlugin({
//定義NODE_ENV環境變數為production,以去除原始碼中只有開發時才需要的部分
"process.env": {
NODE_ENV: JSON.stringify("production")
}
}),
//壓縮輸出的JavaScript程式碼
new UglifyJsPlugin({
// 最緊湊的輸出
beautify: false,
// 刪除所有的註釋
comments: false,
compress: {
// 在UglifyJs刪除沒有用到的程式碼時不輸出警告
warnings: false,
// 刪除所有的 `console` 語句,可以相容ie瀏覽器
drop_console: true,
// 內嵌定義了但是隻用到一次的變數
collapse_vars: true,
// 提取出出現多次但是沒有定義成變數去引用的靜態值
reduce_vars: true,
}
})
]
}
以上配置中,大多數都是按照前面已經講過的內容增加的配置如
- 增加對css檔案的支援, 提取出chunk中的css程式碼到單獨的檔案中,壓縮css程式碼;
- 定義NODE_ENV環境變數為production,以去除原始碼中只有開發時才需要的部分;
- 給輸出的檔名稱加上hash值;
- 壓縮輸出的JavaScript帶啊。