移動spa商城優化記(二)--- 減小70%的打包等待時間

背景

上篇講了首屏優化,具體文章詳見移動spa商城優化記(一)---首屏優化篇,此次來分享一下打包速度的一些優化經驗,由於在實際項目開發中,隨着項目的不斷增大,依賴項不斷增多,咱們會發現webpack打包速度會愈來愈慢,有時候npm run一下可能出去上個廁所的時間都夠了,在這快速發展的時代,這麼拖節奏的事情毫不容許,本篇仍是以公司spa商城爲例,詳細介紹一下優化打包速度方面的經驗。css

開始

公司這個項目的起手模板是vue-cli的webpack模板,項目完成大概有將30個頁面,未經優化前打包時間如圖: html

優化前的時間
大概兩分鐘左右,是否是出去上個廁所的時間都夠了。

接下來開始優化,優化主要分四方面:減小打包文件數量,減小沒必要要的功能開銷,優化打包方式,升級打包工具。前端

1.減小打包文件數量

指導思想:要打包的東西少了速度天然就快了。
vue

1.dll

webpack.DllPlugin + webpack.DllReferencePlugin這組插件應該是借鑑了dll的思想因此叫dllplugin這個名字,目的就是將vue,vue-router,react,jquery等等這些體積較大,項目中不常更新的第三方包抽離出來單獨打包,而後告訴webpack這些包我以前已經打包過了,你每次打包直接用就好了,不用每次再去從新打包一次了。
node

使用方法:
react

  1. build文件夾下新建一個webpack.dll.conf.js,內容能夠這樣寫:
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()
    ]
}

複製代碼
  1. 執行 webpack --config build/webpack.dll.conf.js打包生成抽離的公共包。
    此時src下應該能看到dll目錄及生成的公共包js及json。
    公共包js及json
  2. 正常webpack配置文件裏配置DllReferencePlugin進行關聯
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

2.減小沒必要要的resolve

  1. 看下webpack的每一個rule下面include裏面是否是有多餘的resolve,或者看看有沒有把node_modules文件夾exclude掉。
  2. 用到babel-loader的地方,記得設置cacheDirectory,以利用bable的緩存。
  3. resolve裏面的extensions能夠刪除沒必要要的後綴名自動補全,減小webpack的查詢時間,好比extensions: ['.js', '.vue', '.json','.scss','.css'],寫這麼多自動補全寫代碼的時候是省了後綴名了,可是這須要webpack打包時去自動查詢後綴增長了時間開銷。
  4. import時多使用完整路徑而不是目錄名,如import './components/scroll/index.js'而不是import './components/scroll,減小webpack的路徑查詢。

2.去除沒必要要的功能開銷

指導思想:減小打包過程當中要作的額外的工做
github

咱們的目的就是優化打包速度,那麼與這個無關的沒必要要的功能能夠先暫停掉,用到時再開。

關掉source map。

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的級別來加快打包的速度。

3.優化打包方式:並行

指導思想:並行打包速度固然快。

1.UglifyJSPlugin並行

這個比較好配置,UglifyJSPlugin插件下加一個屬性parallel設爲true便可。

new UglifyJSPlugin({
        parallel: true
        ......
})
複製代碼

還能夠設置打包緩存,具體見下面的配置

UglifyJSPlugin

2.Happypack

Happypack經過多進程模型,來加速代碼構建。
好比說之前使用vue-loader處理vue文件,之前是串行處理,如今利用happypack能夠並行使用vue-loader處理vue文件。

  1. 首先安裝HappyPack
    npm install --save-dev happypack
  2. 修改webpack.base.config.js
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 原理解析

4.升級打包工具

指導思想:鳥槍換大炮,升級打包工具。

  1. 升級node
  2. 升級webpack
    webpack4比3快,3比2快,推薦webpack至少升到3以上,4還不太穩定,強行升級坑較多。
  3. 升級各類loader

不少時候,大神們在冥冥之中已經幫咱們在底層作了優化,咱們根本不須要作什麼配置,咱們只須要升級工具便可,固然,升級的同時要保證項目的健壯性。

最後

一圖勝千言,這是通過優化後的打包時間:

優化後的時間

打包時間從原來的的120s減小到了如今的34s,優化率70%以上。不再用每次npm run 一下就先去上個廁所了。。。

參考文章:
使用 webpack 定製前端開發環境
webpack打包優化解決方案

相關文章
相關標籤/搜索