上篇講了首屏優化,具體文章詳見移動spa商城優化記(一)---首屏優化篇,此次來分享一下打包速度的一些優化經驗,由於在實際項目開發中,隨着項目的不斷增大,依賴項不斷增多,咱們會發現webpack打包速度會愈來愈慢,有時候npm run一下可能出去上個廁所的時間都夠了,在這快速發展的時代,這麼拖節奏的事情毫不容許,本篇仍是以公司spa商城爲例,詳細介紹一下優化打包速度方面的經驗。css
公司這個項目的起手模板是vue-cli的webpack模板,項目完成大概有將30個頁面,未經優化前打包時間如圖: html
接下來開始優化,優化主要分四方面:減小打包文件數量,減小沒必要要的功能開銷,優化打包方式,升級打包工具。前端
指導思想:要打包的東西少了速度天然就快了。
vue
webpack.DllPlugin + webpack.DllReferencePlugin這組插件應該是借鑑了dll的思想因此叫dllplugin這個名字,目的就是將vue,vue-router,react,jquery等等這些體積較大,項目中不常更新的第三方包抽離出來單獨打包,而後告訴webpack這些包我以前已經打包過了,你每次打包直接用就好了,不用每次再去從新打包一次了。
node
使用方法:
react
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry:{
//這地方寫你想抽離的包,能夠參考你的package.json文件下的dependencies
vue:['vue','vue-router']
},
output:{
//這地方寫你打包後生成文件的路徑
path:path.join(__dirname,"../src/dll"),
filename:'[name].dll.js',
library:'[name]'
},
plugins:[
//這個插件是重點,用於打包上面entry裏配置的包
new webpack.DllPlugin({
path:path.join(__dirname,"../src/dll",'[name]-manifest.json'),
name:'[name]',
}),
new webpack.optimize.UglifyJsPlugin()
]
}
複製代碼
webpack --config build/webpack.dll.conf.js
打包生成抽離的公共包。plugins: [
new webpack.DllReferencePlugin({
//這裏寫上一步打包出的json路徑
manifest:require('../src/dll/vue-manifest.json')
})
......
]
複製代碼
如今,再次打包就能夠了,你提取出的第三方包越多,打包速度優化的越明顯。若是想讓打包出的html能夠自動引入第二步打包出的dll.js文件,可使用add-asset-html-webpack-plugin或者本身修改HtmlWebpackPlugin的配置實現打包出的html內自動引入dll.js文件。
jquery
關於HtmlWebpackPlugin詳細配置能夠看這篇文章:
html-webpack-plugin用法全解
關於add-asset-html-webpack-plugin詳細配置能夠看這篇文章:
add-asset-html-webpack-plugin配置webpack
另外使用cdn引入包而後加 externals配置的方式也能夠,思路和dll一致,都是抽離第三方包,只打包業務代碼,只不過這種方式第三方包直接引用cdn上的。git
extensions: ['.js', '.vue', '.json','.scss','.css'],
寫這麼多自動補全寫代碼的時候是省了後綴名了,可是這須要webpack打包時去自動查詢後綴增長了時間開銷。import './components/scroll/index.js'
而不是import './components/scroll
,減小webpack的路徑查詢。指導思想:減小打包過程當中要作的額外的工做
github
咱們的目的就是優化打包速度,那麼與這個無關的沒必要要的功能能夠先暫停掉,用到時再開。
sourcemap有如下幾個配置值:
eval: 生成代碼 每一個模塊都被eval執行,而且存在@sourceURL
cheap-eval-source-map: 轉換代碼(行內) 每一個模塊被eval執行,而且sourcemap做爲eval的一個dataurl
cheap-module-eval-source-map: 原始代碼(只有行內) 一樣道理,可是更高的質量和更低的性能
eval-source-map: 原始代碼 一樣道理,可是最高的質量和最低的性能
cheap-source-map: 轉換代碼(行內) 生成的sourcemap沒有列映射,從loaders生成的sourcemap沒有被使用
cheap-module-source-map: 原始代碼(只有行內) 與上面同樣除了每行特色的從loader中進行映射
source-map: 原始代碼 最好的sourcemap質量有完整的結果,可是會很慢
複製代碼
當咱們不須要調試時,能夠關掉sourcemap或下降sourcemap的級別來加快打包的速度。
指導思想:並行打包速度固然快。
這個比較好配置,UglifyJSPlugin插件下加一個屬性parallel設爲true便可。
new UglifyJSPlugin({
parallel: true
......
})
複製代碼
還能夠設置打包緩存,具體見下面的配置
Happypack經過多進程模型,來加速代碼構建。
好比說之前使用vue-loader處理vue文件,之前是串行處理,如今利用happypack能夠並行使用vue-loader處理vue文件。
npm install --save-dev happypack
const HappyPack = require('happypack');
const vueLoaderConfig = require('./vue-loader.conf')
exports.module = {
rules: [
{
test: /\.vue$/,
//vue-loader替換爲happypack/loader,若是遇到vue文件就用happypack,id指定爲vue
loader: 'happypack/loader?id=vue'
},
{
test: /\.js$/,
//babel-loader替換爲happypack/loader,若是遇到js文件就用happypack,id指定爲js
loader: 'happypack/loader?id=js'
}
......
]
};
exports.plugins = [
new HappyPack({
id:'vue',
//同時開多少線程進行打包,也能夠用ThreadPool控制
threads: 4,
loaders: [{
//這是真實的處理loader,具體配置和rules裏本來的一致,options也照搬過來就行
loader:'vue-loader',
options:vueLoaderConfig
}]
}),
new HappyPack({
id: 'js',
threads: 3,
loaders: [{
loader:'bable-loader',
}]
})
......
];
複製代碼
通過以上配置,咱們就可使用happypack愉快的進行打包了。
更多高級配置能夠看文檔:Happypack文檔
另外,想了解happypack原理的能夠看淘寶團隊的這篇文章:happypack 原理解析
指導思想:鳥槍換大炮,升級打包工具。
不少時候,大神們在冥冥之中已經幫咱們在底層作了優化,咱們根本不須要作什麼配置,咱們只須要升級工具便可,固然,升級的同時要保證項目的健壯性。
一圖勝千言,這是通過優化後的打包時間:
打包時間從原來的的120s減小到了如今的34s,優化率70%以上。不再用每次npm run 一下就先去上個廁所了。。。