拥抱webpack4,有效缩减构建时间57%+

背景

最近有感觉到,随着系统模块数量的增加,wepack编译打包的速度越来越慢,于是我想给项目做一下优化升级,也借此机会系统地学习一下webpack4

升级过程

当前版本

"dependencies": {
    "@fullcalendar/core": "^4.2.0",
    "@fullcalendar/daygrid": "^4.2.0",
    "@fullcalendar/interaction": "^4.2.0",
    "@fullcalendar/vue": "^4.2.2",
    "axios": "0.18.1",
    "babel-polyfill": "6.26.0",
    "echarts": "4.0.4",
    "element-ui": "2.10.0",
    "jquery": "3.3.1",
    "js-cookie": "2.2.0",
    "js-md5": "0.7.3",
    "lodash": "4.17.5",
    "moment": "^2.24.0",
    "node-sass": "^4.11.0",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "qs": "6.5.1",
    "vue": "2.6.10",
    "vue-router": "3.0.3",
    "vuex": "3.1.1"
},
"devDependencies": {
    "autoprefixer": "7.2.3",
    "babel-core": "6.26.0",
    "babel-eslint": "8.0.3",
    "babel-helper-vue-jsx-merge-props": "2.0.3",
    "babel-loader": "7.1.2",
    "babel-plugin-syntax-jsx": "6.18.0",
    "babel-plugin-transform-runtime": "6.23.0",
    "babel-plugin-transform-vue-jsx": "3.7.0",
    "babel-preset-env": "1.6.1",
    "babel-preset-stage-2": "6.24.1",
    "chalk": "2.3.0",
    "copy-webpack-plugin": "4.2.3",
    "css-loader": "0.28.7",
    "eslint": "4.13.1",
    "eslint-friendly-formatter": "3.0.0",
    "eslint-loader": "1.9.0",
    "eslint-plugin-html": "4.0.1",
    "eventsource-polyfill": "0.9.6",
    "extract-text-webpack-plugin": "3.0.2",
    "file-loader": "1.1.5",
    "friendly-errors-webpack-plugin": "1.6.1",
    "html-webpack-plugin": "2.30.1",
    "node-notifier": "5.1.2",
    "optimize-css-assets-webpack-plugin": "3.2.0",
    "ora": "1.3.0",
    "portfinder": "1.0.13",
    "postcss-import": "11.0.0",
    "postcss-loader": "2.0.9",
    "rimraf": "2.6.2",
    "sass-loader": "6.0.6",
    "semver": "5.4.1",
    "shelljs": "0.7.8",
    "svg-sprite-loader": "4.1.6",
    "uglifyjs-webpack-plugin": "1.1.3",
    "url-loader": "0.6.2",
    "vue-loader": "15.7.0",
    "vue-style-loader": "4.1.2",
    "vue-template-compiler": "2.6.10",
    "webpack": "3.10.0",
    "webpack-bundle-analyzer": "2.9.1",
    "webpack-dev-server": "2.9.7",
    "webpack-merge": "4.1.1"
}

目标版本

"dependencies": {
    "@fullcalendar/core": "^4.2.0",
    "@fullcalendar/daygrid": "^4.2.0",
    "@fullcalendar/interaction": "^4.2.0",
    "@fullcalendar/vue": "^4.2.2",
    "axios": "0.18.1",
    "babel-polyfill": "6.26.0",
    "echarts": "4.0.4",
    "element-ui": "2.10.0",
    "jquery": "3.3.1",
    "js-cookie": "2.2.0",
    "js-md5": "0.7.3",
    "lodash": "4.17.5",
    "moment": "^2.24.0",
    "node-sass": "^4.11.0",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "qs": "6.5.1",
    "vue": "2.6.10",
    "vue-router": "3.0.3",
    "vuex": "3.1.1"
},
"devDependencies": {
    "autoprefixer": "9.6.1",
    "babel-core": "6.26.3",
    "babel-eslint": "10.0.3",
    "babel-helper-vue-jsx-merge-props": "2.0.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-syntax-jsx": "6.18.0",
    "babel-plugin-transform-runtime": "6.23.0",
    "babel-plugin-transform-vue-jsx": "3.7.0",
    "babel-preset-env": "1.7.0",
    "babel-preset-stage-2": "6.24.1",
    "chalk": "2.4.2",
    "copy-webpack-plugin": "5.0.4",
    "css-loader": "3.2.0",
    "eslint": "6.3.0",
    "eslint-friendly-formatter": "3.0.0",
    "eslint-import-resolver-webpack": "^0.11.1",
    "eslint-loader": "3.0.0",
    "eslint-plugin-vue": "^5.2.3",
    "eventsource-polyfill": "0.9.6",
    "file-loader": "4.2.0",
    "friendly-errors-webpack-plugin": "1.7.0",
    "html-webpack-plugin": "3.2.0",
    "mini-css-extract-plugin": "^0.8.0",
    "node-notifier": "5.1.2",
    "optimize-css-assets-webpack-plugin": "3.2.0",
    "ora": "1.3.0",
    "portfinder": "1.0.13",
    "postcss-import": "12.0.1",
    "postcss-loader": "3.0.0",
    "rimraf": "2.6.2",
    "sass-loader": "8.0.0",
    "semver": "5.4.1",
    "shelljs": "0.7.8",
    "svg-sprite-loader": "4.1.6",
    "uglifyjs-webpack-plugin": "2.2.0",
    "url-loader": "2.1.0",
    "vue-loader": "15.7.1",
    "vue-style-loader": "4.1.2",
    "vue-template-compiler": "2.6.10",
    "webpack": "4.39.3",
    "webpack-bundle-analyzer": "3.4.1",
    "webpack-cli": "^3.3.8",
    "webpack-dev-server": "3.8.0",
    "webpack-merge": "4.2.2"
}

第一步

升级webpack4.39.3版本,npm run dev遇到了报错......

npm run dev报错

webpack-dev-server版本过低

Error: Cannot find module 'webpack/bin/config-yargs'

应该是webpackwebpack-dev-server版本不符,于是升级webpack-dev-server3.8.0版本。

webpack-cli缺失

The CLI moved into a separate package: webpack-cli
Please install 'webpack-cli' in addition to webpack itself to use the CLI
-> When using npm: npm i -D webpack-cli
-> When using yarn: yarn add -D webpack-cli
internal/modules/cjs/loader.js:584
    throw err;
    ^

Error: Cannot find module 'webpack-cli/bin/config-yargs'

webpack4webpack-cli单独分离出来了,因此提示我们安装webpack-cli,那就直接安装吧。

html-webpack-plugin版本问题

10% building 2/2 modules 0 active(node:8596) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
(node:8596) DeprecationWarning: Tapable.apply is deprecated. Call apply on the plugin directly instead
53% building 363/366 modules 3 active D:\coollu\projects\coollu-v3\source-code\develop\coollu-cloud-web\node_modules\core-js\modules\_array-reduce.jsD:\coollu\projects\coollu-v3\source-code\develop\coollu-cloud-web\node_modules\html-webpack-plugin\lib\compiler.js:81
        var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
                                                  ^

TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function

考虑是html-webpack-plugin版本问题,升级至3.2.0

extract-text-webpack-plugin?

10% building 2/2 modules 0 active(node:19732) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead

查到是因为extract-text-webpack-plugin不再支持webpack4.3,需要改用mini-css-extract-plugin

ps: extract-text-webpack-plugin是用来抽取依赖的.css文件的,防止样式全部打包在js bundle里太大。改用了mini-css-extract-plugin后,该报错并未消除,考虑要用compiler钩子重写一些东西,先在这埋个坑,后面弄明白了再来填坑。

eslint-loader升版本

Module build failed (from ./node_modules/eslint-loader/index.js):
TypeError: Cannot read property 'eslint' of undefined
    at Object.module.exports (D:\coollu\projects\coollu-v3\source-code\develop\coollu-cloud-web\node_modules\eslint-loader\index.js:148:18)

升级eslint-loader

file-loader升版本

Module build failed (from ./node_modules/file-loader/dist/cjs.js):
TypeError: Cannot read property 'context' of undefined
    at Object.loader (D:\coollu\projects\coollu-v3\source-code\develop\coollu-cloud-web\node_modules\file-loader\dist\index.js:34:49)

升级file-loader

npm run build报错

改用splitChunks

webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.

使用webpack4optimization.splitChunks替代CommonsChunkPlugin

vue-loader升版本

ERROR in ./src/App.vue?vue&type=style&index=0&id=7c362b6c&lang=scss&scoped=tr (./node_modules/mini-css-extract-plugin/dist/loader.js??ref--10-0!./node_mods/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=0&id=62b6c&lang=scss&scoped=true&)
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.:
ModuleParseError: Module parse failed: Unexpected character '#' (14:0)
File was processed with these loaders:
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.

考虑是vue-loader版本问题,先升级vue-loader@15.7.1

babel-loader降版本

ERROR in ./src/main.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module '@babel/core'
 babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'd like to use Babel 6.x ('babel-core'), you should install 'babel-loader@7'.

babel-loader@8降低了版本,调整为babel-loader@7

ps: 想了一下,觉得可能其他的loader版本也会过低,于是将其他的loader都进行了升级,具体见package.json

优化打包速度

happypack

一个号称用多进程策略提升webpack打包速度的插件,真的挺管用的。

happypack允许您并行转换多个文件,从而加快了webpack的构建速度。

安装:

npm install --save-dev happypack

简单配置如下:

const HappyPack = require('happypack')

// webpack配置,只列出关于happypack的配置
rules: [
  // ...其他rule
  {
    test: /\.js$/,
    // 注释掉原来的babel-loader,改用happypack/loader
    // loader: "babel-loader",
    use: ['happypack/loader'],
    include: [
      resolve("src")
    ]
  }
],
plugins: [
  // ...其他plugin
  // 安装说明简单配置了一下
  new HappyPack({
    // 将我们刚才注释的loader放在这,告诉happypack
    loaders: ['babel-loader'],
    // 开启4个子进程,据说是最优解
    threads: 4
  })
]

总结

经过大量npm包版本的调整,以及webpack配置的修改(主要是optimization的调整;把extract-text-webpack-plugin换成了mini-css-extract-plugin;加入了happypack),报错基本上消除了,经测试,devprod环境都没有功能上的问题,热加载,编译,打包速度确实得到了显著提升。

  • 热加载

    速度得到了显著提升,之前改一行代码,热加载编译的时间差不多要花1min,让人难受;优化后,基本上控制在<=5s

  • webpack升级前打包:

    Hash: 35f207120dd3736758dd
    Version: webpack 3.10.0
    Time: 95987ms
    

    大概需要96s的打包时间。

  • webpack升级后打包:

    Hash: fb73468076752cad58f6
    Version: webpack 4.39.3
    Time: 61597ms
    

    打包时间降低到61.6s,节约了34.4s,打包效率提升了35.8%以上。

  • 使用happypack后:

    Happy[1]: Version: 5.0.1. Threads: 4
    Happy[1]: All set; signaling webpack to proceed.
    Hash: a635e8b39b7064adf41c
    Version: webpack 4.39.3
    Time: 41047ms
    

    打包时间降低到41s,再次节约了20.6s!总共节约了55s,与升级前相比,打包效率提升了57%以上。

当然可优化的空间还很大,webpack4还有很多东西值得我们去折腾,优化之路还在继续!

首发链接


扫一扫下方小程序二维码或搜索Tusi博客,即刻阅读最新文章!

Tusi博客
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容