webpack打包速度和性能再次優化


一. 改單dll為雙dll

因為上圖原因,使用CommonsChunkPlugin時,導致其打包出來的vendors.js內的模塊ID會因為其他文件引用模塊數量的變化而變化。

所以現利用DllPlugin打包原vendors.js打包的文件,命名依然為vendor,文件名:vendor.js。


二. 利用cache和多線程提高編譯速度:
 

時間(s) 優化前 優化后
webpack cach:true 55 54
babel-loader?cacheDirectory=true 54 35
webpack-parallel-uglify-plugin 36.7 27.98
 happypack  36 34.33
uglifyjs-webpack-plugin 39 21.20

 

 

 

 

 

 

三. 更換js壓縮插件為:uglifyjs-webpack-plugin

可以使用多線程加速,但有一個問題,目前使用版本是:1.1.8

此插件壓縮功能只支持如下配置:

output: {
        filename: 'js/[name].[chunkhash:8].js'
    }

或

output: {
        filename: 'js/[name].js'
    }

不支持:

output: {
        filename: 'js/[name].js?v=[chunkhash:8]'
    }

 

相關issue:  https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/220

 

基於以上原因,更改覆蓋式發布為非覆蓋式發布方式 js/[name].[chunkhash:8].js , 這時你可能會用到如下插件來動態插入css和js:

功能對比 add-asset-html-webpack-plugin html-webpack-include-assets-plugin 備注
hash 

根據具體文件內容計算哈希值

自動加在文件名后:xxx?as68d7

webpack編譯環境hash值,所有文件的hash值統一,且一旦編譯環境有改動,hash即變化

自動加在文件名后:xxx?as68d7

 
待插入文件 filepath字段,支持glob assets字段,支持glob  
插入html的位置 head或body最后,其他引用資源的前面,不可選擇位置 可選擇插入在其他引用資源的前面或后面

其他引用資源值htmlWebpackPlugin

插入的資源

copy文件 會把filepath文件copy到publicPath下 不會copy文件  

 

 

 

 

 

 

 

 

 

 

舉例如下:

new AddAssetHtmlPlugin([
          { 
              filepath: outDir + '/js/lib/dll.js',
              publicPath: outPublicDir + 'js/lib/',
              outputPath: './js/lib',
              hash: true,
              includeSourcemap: false
          },
          { 
              filepath: outDir + '/js/vendor.js',
              publicPath: outPublicDir + 'js/',
              outputPath: './js',    
              hash: true,
              includeSourcemap: false
          },
          { 
              filepath: outDir + '/css/vendor.css',
              publicPath: outPublicDir + 'css/',
              outputPath: './css',
              hash: true,
              includeSourcemap: false,
              typeOfAsset:'css'
          }
        ])
new HtmlWebpackIncludeAssetsPlugin({
    assets: [getLatestFile('js/lib/dll.js')],
    append: false
}),
new HtmlWebpackIncludeAssetsPlugin({
    assets: [getLatestFile('js/vendor.js')],
    append: false
}),
new HtmlWebpackIncludeAssetsPlugin({
    assets: [getLatestFile('css/vendor.css')],
    append: false
})

 

對比后選擇:html-webpack-include-assets-plugin,動態順序插入dll.js, vendor.js, manifest.js和頁面功能js由htmlWebpackPlugin插入到最后。

再此基礎上,需要手動檢索最新的dll.xxx.js 和vendor.xxx.js文件:

getLatestFile('js/vendor.js')

function getLatestFile(path){
    let new_path = path.replace(/\./g, '.**.');
    let latest_file = '';
    let latest_file_mtime = 0;

    glob.sync(outDir + '/' + new_path).forEach(function(file){
        let fileInfo = fs.statSync(file);
        let file_mtime = +new Date(fileInfo.mtime);

        latest_file = file_mtime > latest_file_mtime ? file : latest_file;
        latest_file_mtime = file_mtime > latest_file_mtime ? file_mtime : latest_file_mtime;

    })

    return latest_file.replace(/^.*\/(js\/|css\/)/ig, "$1");
}

 

有個問題即,如果你是本地編譯后上傳發布編譯后的代碼,那么因為是非覆蓋式發布,manifest.js內的runtime一直變化導致所有引入manifest的html 都會變化。這個問題目前解決方案是把編譯部署這兩步移到服務器進行,我們只關注並提交源碼即可。比如可以利用gitlab+jenkins的方式。

 

附:nodejs一些常用方法簡介

glob:

基於javascript, 使用 minimatch 庫(各種正則)來進行匹配獲取文件路徑

var glob = require("glob")

// options 是可選的
glob("**/*.js", options, function (er, files) {
  // files 是匹配到的文件的數組.
  // 如果 `nonull` 選項被設置為true, 而且沒有找到任何文件,那么files就是glob規則本身,而不是空數組
  // er是當尋找的過程中遇的錯誤
})

glob.sync() 同步獲取

var files = glob.sync(pattern, [options])

 

fs:

Node.js內置的fs模塊就是文件系統模塊,負責讀寫文件。和所有其它JavaScript模塊不同的是,fs模塊同時提供了異步和同步的方法。

fs異步:

'use strict';

var fs = require('fs');

fs.readFile('sample.txt', 'utf-8', function (err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

fs同步:

try {
    var data = fs.readFileSync('sample.txt', 'utf-8');
    console.log(data);
} catch (err) {
    // 出錯了
}

 

path.resolve:  相對路徑轉絕對路徑

path.stat: 獲取文件屬性比如大小,時間等

 

附2:自己根據文件內容計算文件hash值方法:

 
         

 const fs = require('fs');
 const crypto = require('crypto');

function getFileHash(path){
    let file = fs.readFileSync(path);
    let hash = crypto.createHash('md5');
    hash.update(file);

    return hash.digest('hex');
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM