背景

前段时间在某个项目进行需求开发的时候,该项目是基于 webpack3 进行打包构建的。在开发过程中我发现打包很慢,开发体验不佳,于是做了简单的优化并梳理了优化方案

分析打包速度

进行优化的第一步需要知道我们的构建到底慢在那里。通过 speed-measure-webpack-plugin 测量你的 webpack 构建期间各个阶段花费的时间:

// 分析打包时间
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
const smp = new SpeedMeasurePlugin()
// ...
module.exports = smp.wrap(prodWebpackConfig)

我们可以看到打包速度慢主要是因为对样式文件和对 js 文件的处理 loader 耗时较久

当文件发生修改,进行重新编译时,此时的打包各阶段时间如下

重新编译时耗时其实并不久,但是在浏览器上实际上却花费了更多的时间在看到了新的修改,这是为何呢

分析 bundle 包

  • 打包后的 bundle 文件生成一个分析文件
"analyse": "webpack --config ./webpack.config.js --profile --json>states.json"

  • 对 json 文件进行分析

我们可以看到在使用 webpack 3.5.6 进行打包的过程中涉及到了 705 个模块,生成了 2 个 chunks, 耗时约 51s

  • 进一步分析 chunks 文件

打包出的两个 chunks 文件分别为 app 和 vendor 文件,其中 app.js 文件体积高达 6M

在绝大多数的情况下,应用刚开始工作时,并不是所有的模块都是必需的。如果这些模块全部被打包到一起,即便应用只需要一两个模块工作,也必须先把 bundle.js 整体加载进来,而且前端应用一般都是运行在浏览器端,这也就意味着应用的响应速度会受到影响,也会浪费大量的流量和带宽。

开发环境下的 bunlde 依赖表也能看出 node_modules 中大部分内容是随着 app.js 一起打包,这些就是引起我们打包速度缓慢的元凶

  • 当我们代码有更新时,HMR 会重新打包 app.js,也就是说那些没有被修改的 node_modules 中内容也会跟着重新打包到 app.js 中去

这意味着,每次代码修改,浏览器都会重新加载这个 6M 大的文件,所以为啥改了一点点内容,浏览器也需要很久才有反应,元凶在这

  • Bundle optimize Helper 的优化建议

Entrypoints are code that are loaded on page load. To get best possible user experience, you should keep the total size of entrypoints to less than 200kb and load the rest dynamically by using code splitting.

我们将 json 文件上传到 Bundle optimize Helper 得到的优化建议是去进行代码分割,入口文件的代码体积不要超过 200K

优化

代码分割

高达 6M 的入口文件显然是非常影响体验的,因此优化的第一步就是从代码分割开始。代码分割通过把项目中的资源模块按照我们设计的规则打包到不同的 bundle 中,从而降低应用的启动成本,提高响应速度。

  • 项目本身已经配置了多入口,将 lodash 等三方库文件单独进行打包,生成 vendor.js 文件
  • 将入口文件依赖的 node_modules 中内容打包到 common 中,将业务代码进行单独打包,这样可以有效减少 app.js 的体积
new webpack.optimize.CommonsChunkPlugin({name: 'common',minChunks: function(module) {return (module.resource &&/.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, './node_modules')) === 0)}
})

  • 再使用一次 CommonsChunkPlugin 抽取 mainfest.js 文件,保证 common.js 的 hash 不会因为每次打包发生变化
new webpack.optimize.CommonsChunkPlugin({name: 'manifest',chunks: ['vendor', 'common', 'app']
}),

  • 使用 HashedModuleIdsPlugin 来保持模块引用的 module_id 不变,CommonsChunkPlugin 提取入口指定的依赖独立打包,mainifest 则保存运行时的函数和模块标识

可以看到此时 app.js 中以来的一些三方库被单独抽取出来了,体积从 6M 降至 3.49 M

  • 当修改业务代码时我们看下新的打包文件

当我们的业务代码发生修改时,会重新进行打包,而依赖的三方库并不会重新打包,此时重新打包的业务代码 app.js 体积也为 3.49M

我们可以看到没有变更的依赖包会走 304 协商缓存,而有变更的 app.js 的会重新请求并且因为体积比之前小,加载性能得到了优化

速度优化

在前面的速度分析中我们已经知道了打包速度主要耗费在 loader 的处理上

很显然在开发过程中进行 webpack 缓存是极其有必要的,我们在处理样式文件和 js 文件的 loader 之前添加 cache-loader 将结果缓存到磁盘中,可以显著提升二次构建速度

module.exports = {module: {rules: [{test: /.js$/,use: ['cache-loader', ...loaders],include: path.resolve('src'),},{test: /.scss$/,use: ['cache-loader', ...loaders],include: path.resolve('src'),},],},
};

加入缓存后我们可以看到打包速度有了显著的提升

进行优化后我们可以看到:优化后入口包体积缩小 42%,打包速度从 51s 提升至 11s

Do More

wepack 的打包优化没有固定的模式,需要我们针对项目去进行分块、拆包、压缩等,常见的优化思路主要分为四部分

  • 优化搜索时间,即开始打包时获取所有的依赖模块的时间
  • 优化解析时间,即根据配置的 loader 解析相应文件所花费的时间
  • 优化压缩时间,即 wepack 对代码进行优化压缩所花费的时间
  • 优化二次打包时间,即重新打包时所花费的时间

在当前的生产构建时会使用 UglifyJsPlugin 来进行代码压缩,但这个插件是单线程的,压缩时会将代码先解析为 AST 抽象语法树,然后根据规则去分析和处理 AST, 最后再将处理后的 AST 还原为 JS 代码,这种涉及大量运算的操作都是非常耗时的。在 Webpack4 中内置了 TerserPlugin 来处理 JS 代码的压缩,我们可以开启多进程压缩模式,可以进一步优化我们的打包速度

我们对 chunks 进行代码分割,但目前 app.js 在未压缩的情况下体积为 3.49M,依然比较大,Webpack4 中 splitChunks 中提供了更为丰富的配置规则,我们可以将代码中公共的部分抽取出来,以及异步加载的模块进行抽取,这样也可以进一步优化代码体积

考虑到项目的稳定性,我们将延后进行 webpack 的升级改造。

以上是本次基于 webpack 优化项目开发体验的小结。了解 webpack 的打包原理,使用 webpack 新特性,一定可以给我们带来更佳的开发体验。

webpack打包优化_如何提升 Webpack 打包速度相关推荐

  1. webpack打包优化_前端性能优化:webpack性能调优与Gzip原理

    链接:https://juejin.im/book/5b936540f265da0a9624b04b 从输入 URL 到显示页面这个过程中,涉及到网络层面的,有三个主要过程: DNS 解析 TCP 连 ...

  2. webpack打包优化_提速MAX 京东通天塔WEBPACK构建发布优化实践

    通天塔作为运营.商家搭建营销活动页的主力系统,数年来一直致力于提供用户更丰富.更强大的搭建体验.通天塔可视化CMS(简称可视化)作为直面商家运营搭建的第一层,在系统能力越来越强大的同时,自身的代码量. ...

  3. webpack版本查看_浅谈webpack技术

    今天来谈一谈基于javascript性能优化问题 为提升文件加载速度,项目需要合并JavaScript代码并且尽量少用标签 通过给

  4. windows2008开机占用多少内存_如何提升电脑开机速度?

    如何提升电脑开机速度? 电脑开机速度很慢是一个很常见的问题,电脑开机时,一些默认的软件会伴随启动.影响电脑开机速度的因素有很多,本期分享我们将讲解如何加快电脑开机速度. 一.禁用无用开机启动项: 将不 ...

  5. webpack打包流程_了不起的 Webpack 构建流程学习指南

    最近原创文章回顾: <了不起的 tsconfig.json 指南> <了不起的 Webpack HMR 学习指南(含源码分析)> <<你不知道的 Blob>番 ...

  6. webpack 处理字体_如何在webpack中更优雅的处理字体图标

    作者:牟金涛 字体图标是目前前端中最常见的一种静态资源,目前大部分的框架或者网站都会将一些简单的图标合并生成一个字体文件而不是合并成雪碧图.其优点显而易见,字体图标能够更加方便的控制图标的大小和颜色, ...

  7. 打包指令_将Vue项目打包为Windows应用(.exe)

    2021年1月9日更新: 新增:解决国内用户下载electron速度太慢的问题 调整:由于electron版本升级,删除原文中对electron版本限制在2.0的命令行语句 背景 朋友是做商品零售,每 ...

  8. vs vue 查看webpack安装成功_在Vue+webpack中详细讲解基础配置

    这篇文章主要介绍了Vue+webpack项目基础配置教程,需要的朋友可以参考下. 最近在学习webpack,跟着课程一个单页面应用,在这里记录一下. 这个部分主要讲了如何配置webpack的环境,以及 ...

  9. webpack 谷歌地图_如何在Webpack中设置可靠且可维护的Google Analytics(分析)

    webpack 谷歌地图 One of the messier bits of a new app setup is trying to figure out where to stash your ...

最新文章

  1. 人字拖藏SIM卡、戴微型蓝牙耳机!为考教师岗,多人作弊被抓
  2. 关于S3C2440扩展SDRAM的地址连线
  3. hdu 1233 最小生成树
  4. html 右边是iframe 左右结构_站点的内链优化和一些常用的结构优化方法
  5. Canvas的基本用法
  6. Java字符串拼接“+”需要注意的问题
  7. python夹角余弦雷达图_P19 从三角形夹角计算看math模块
  8. 关于IPMI的几个问题
  9. linux关于管道通信,球热心人帮忙 关于linux环境下管道通信
  10. Java8 Stream()引发的“non-static method cannot be referenced from a static context”
  11. 1195 巧妙推算走楼梯(宁波大学oj)
  12. Mathematica基础教程
  13. sketchup的SKP格式转到导入supermap需要的GLTF格式
  14. Navicat Premium 12破解方法
  15. 基于3DGIS+BIM的智慧园区运维管理平台
  16. 重新训练大脑!这些APP可治愈心理疾病
  17. Ubuntu16.04下安装QQ的完整操作记录(经验证可用)
  18. flex横向纵向间距,自适应排列
  19. vue中怎么获取元素
  20. mac中执行命令ifconfig: invalid arguments

热门文章

  1. [Python+sklearn] 拆分数据集为训练和测试子集 sklearn.model_selection.train_test_split()
  2. kubernets 集群和本地环境联调环境打通工具kt-connect
  3. java图片色阶调整、亮度调整
  4. js排序算法详解-选择排序
  5. 准备mybatis-spring
  6. 用户故事与敏捷方法笔记 --- 用户故事
  7. springboot学习笔记-3 整合redismongodb
  8. Java零基础系列003——变量
  9. HDU 1010 深搜+奇偶剪枝
  10. Ext中的get、getDom、getCmp、getBody、getDoc的区别