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');
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

DOS常用命令大全

2010-04-17 22:27:19|  分类: 电脑技术 |  标签:dos命令大全 |字号大中小 订阅

1881
来自专栏云霄雨霁

应用层的常见协议

1750
来自专栏Python研发

LInux50个基本命令

cd:(切换) vim:(创建文件)   vi:编辑文件 bc:(计算器)quit:退出计算器 mkdir:(创建目录)   mkdir -p:递归建立目录 r...

1313
来自专栏大闲人柴毛毛

Linux系统服务——Daemon

什么是Daemon? Daemon是Linux的一些系统服务,它们是一些常驻内存的进程。 Daemon分类 Daemon拥有两种分类方式,按照“daemon是...

3334
来自专栏SDNLAB

【连载-4】数据中心网络虚拟化 配置管理技术

在构建虚拟网络时,管理员需要进行大量的配置工作,例如端口的ip地址和VXLAN配置等等。显然,没有人愿意在系统每次启动时都将繁琐的配置工作重复一遍,所以将配置信...

2765
来自专栏difcareer的技术笔记

JNI实现源码分析【五 结束语】正文

一开始打算用一篇文章来写的,结果写着写着,发现内容实在太多了,一篇文章显得很乱,有很多地方不知道先写哪个好,经过一段时间的构思后,决定用一个系列来写,分多个部分...

975
来自专栏ImportSource

GitHub不count contributions的解决办法

最近在github上提交代码,发现push上去代码以后,在Public activity 里是有记录的,如下: ? 但在Contribution activi...

3366
来自专栏SDNLAB

SDN开发笔记(一):SDN开发环境的搭建(win7环境)

前言 鉴于网上对于SDN开发相关的资料较少又乱的现状,从这篇文章开始,我将陆续分享我在SDN开发过程中的经验,我的SDN项目开发是基于OpenDaylight的...

4188
来自专栏PHP在线

PHP错误类型及屏蔽方法

程序只要在运行,就免不了会出现错误,错误很常见,比如Error,Notice,Warning等等。这篇文章具体说一下PHP的错误类型和屏蔽方法。在PHP中,主要...

3618
来自专栏华仔的技术笔记

Block类型变量-缓存Http请求与回调

3436

扫码关注云+社区