移动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打包优化解决方案

相关文章
相关标签/搜索