用实验的思路优化webpack4项目编译速度

最近开发的时候遇到一个问题:当项目愈来愈大的时候,webpack构建和编译的速度变得很慢。尽管webpack4官方宣称速度提升了90%以上,但实际使用的时候感受速度和webpack2也差很少。我实在受不了热加载的时候要等几秒才能编译好,因而就开始了优化之路。
最终优化的效果不错,提速达到了80%以上。一路上按着之前作实验的思惟去优化,经历了各类问题,相比于分享解决问题的方法,我反而更想分享下解决问题的思路。html

先量化目标

通常作实验以前,咱们都要先定一个目标。
可是问题来了,虽然感受很慢,但我不知道具体花了多少时间,慢是慢在哪里,因此也没办法知道咱们能够优化到什么程度,优化也无从下手了。 因而首要的任务就是得到webpack编译过程的信息。
在webpack的官方文档中找了一大圈后,发现了配置中devServer.stats属性能够得到编译过程的完整信息node

stats: {
    timings: true,
    modules: false,
    assets: false,
    entrypoints: false,
    assetsSort: 'field',
    builtAt: false,
    cached: false,
    cachedAssets: false,
    children: false,
    chunks: false,
    chunkGroups: false,
    chunkModules: false,
    chunkOrigins: false,
    performance: true,
    errors: true,
    warnings: true,
},
复制代码

配成这样以后获得了构建和编译的时间:webpack

能够看到构建时间是40s,改动代码后编译的时间是5.4s。
既然webpack4宣称能够提速90%,那目前的状况确定是有某些地方配置不当,咱们就先定个目标,将编译时间优化到1s如下。

猜想可能影响速度的因素

目前的项目是多入口的项目,每一个入口之间没有太多的关联,可是却放在了一块儿打包和编译。咱们平时开发的时候若是每次只编译一个入口的文件会不会快一点呢?
本来有三个入口,只加载一个入口的时候能够看到:git

构建和编译的速度都加快了。变成了30s和3.4s。
既然有效,就写几个命令来方便开发不一样的入口:

"scripts": {
    "dev": "webpack-dev-server --config ./webpack.config/dev.js --hot --inline",
    "teacher": "app=teacher webpack-dev-server --config ./webpack.config/dev.js --hot --inline",
    "student": "app=student webpack-dev-server --config ./webpack.config/dev.js --hot --inline",
    "home": "app=home webpack-dev-server --config ./webpack.config/dev.js --hot --inline",
    }
复制代码

在package.json中dev命令前加了一个app=XXX的参数github

const teacherEntry = {
    ueditor: [
        'babel-polyfill',
        './src/common/UEditor/ueditor.config.js',
        './src/common/UEditor/ueditor.all.js',
        './src/common/UEditor/kityformula-plugin/addKityFormulaDialog.js',
        './src/common/UEditor/kityformula-plugin/getKfContent.js',
        './src/common/UEditor/kityformula-plugin/defaultFilterFix.js'
    ],
    teacher: ['./src/app/teacher/index.js'],
    teacherLogin: './src/app/teacherLogin/js/teacherLogin.js'
};
const studentEntry = {
    student: ['babel-polyfill', './src/app/student/index.js'],
    studentLogin: './src/app/studentLogin/js/studentLogin.js'
};
const homeEntry = {
    home: './src/app/home/index.js'
};
const entryObj = {
    teacher: teacherEntry,
    student: studentEntry,
    home: homeEntry
};

const entry = process.env.app
    ? entryObj[process.env.app]
    : Object.assign({}, teacherEntry, studentEntry, homeEntry);
复制代码

而后在webpack.base.config.js中加上了根据process.env.app的值来加载不一样入口的代码,这样就实现开发时跑不一样的命令加载不一样入口的效果了。web

检查webpack config中是否有影响性能的配置

接下来就用控制变量的方法去逐个去掉webpack的loader和plugin,而后观察减小的时间了。json

new WriteFilePlugin({
    test: /^((?!hot-update).)*$/
}),
复制代码

发现用到了一个写入文件的插件,将全部文件都写到出口了,但实际上只须要写入html文件就好了,因而改为缓存

new WriteFilePlugin({
    test: /\.html$/,
    useHashIndex: true
}),
复制代码

改后构建和编译时间变成了30s和3s,有了一点点优化。
而后发现babel编译js的时候没有忽略掉node_modules目录。bash

{
    test: /\.js$/,
    include: /(src|node_modules\/flv.js)/,
    exclude: /(node_modules)/,
    loader: 'babel-loader'
},
复制代码

加上后发现时间变成了27s和2.2s,已是一开始的一半了。babel

对比别人的项目看有没有能够借鉴的地方

配置看得差很少了,没有再发现有问题的地方了,因而开始google查找别人的优化方法。
后来找到了一个相似的项目用了happypack(多线程编译)和cache-loader(缓存),感受优化效果还不错:

new HappyPack({
    id: 'babel', // 对于loaders id
    loaders: ['cache-loader', 'babel-loader?cacheDirectory'], // 是用babel-loader解析
    threadPool: happyThreadPool,
    verboseWhenProfiling: true // 显示信息
}),
复制代码

加上了happypack和cache-loader以后能够看到第一次构建速度有了很大的提高,减小到了13.5s!
可是编译的速度基本没什么变化,仍是2s。革命还没有成功,同志仍需努力啊。

观察编译过程的信息,寻找优化点

要进一步优化编译的速度,只好去分析编译的过程到底发生了什么问题了。
将stats中的assets设置为true,观察编译的文件:

发现每个js文件都有一个相同大小的.map文件,这样岂不是会花费一倍的时间!?因而赶忙谷歌查一下.map文件是何方神圣。 后来发现它来自于webpack配置中的devtool,主要用于调试程序,官方配置说明以下:

原来项目中一直是用了最慢的source-map!因而赶忙修改配置:

devtool: 'cheap-module-eval-source-map'
复制代码

改完后试了一下,构建和编译时间缩短为11s和0.8s。

终于将编译速度降到了1s一下,完成了最初定下的目标。

总结

通过这一路的优化以后,深感webpack的配置博大精深。每一个项目可能都有不一样的问题影响着webpack的速度,因此在此分享定位问题的思路,但愿能帮助遇到相似问题的朋友一步步找到问题,提升速度。

Author: Brady

相关文章
相关标签/搜索