-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
基于 roadhog^2.x 的后台项目构建性能优化 #1
Labels
Comments
请问文中提到extraBabelPlugins是什么插件呢 |
extraBabelPlugins 其实就是对应到 webpack 中 babel-loader 的配置项 babel plugin 列表。 对应 roadhog 中的位置是下面这里。 这里传给 umi/af-webpack(v0.23.beta-1)的 getConfig 方法,这个方法就是用来生成 Webpack 配置的。具体位置在下面这里。 简化中间的流程,相当于 Webpack 配置中的对 js 和 jsx 以及 ts 相关的文件应 babel-loader 解析。 {
module: {
rules: [
{
test: /\.js$/,
include: opts.cwd,
exclude: /node_modules/,
use: [
{/* debugLoader.js */},
{
loader: require.resolve('babel-loader'),
options: {
plugins: config.extraBabelPlugins /* 相当于这里 */
}
}
],
},
{
test: /\.jsx$/,
include: opts.cwd,
use: babelUse,
},
]
}
} 这里所说的 extraBabelPlugins 会按需加载,主要是 antd 团队提供了一个 babel-plugin-import,能够过滤掉引用 antd 但是却没有使用到的组件。 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
技术选型
目前我司后台系统采用基于 Webpack 为底层封装的打包工具 roadhog。开发者通过工具暴露的有限的可配置参数,可以简单明了地针对项目需要进行自定义配置。该款工具的目的很明确,就是为了简化 webpack 的配置。这对于入门级别的工程师是非常友好的,因为降低了学习 webpack 的成本,免去捣鼓 webpack 复杂的配置,方便开发者快速进入开发流程。
从目前项目版本的
package.json
向上层依赖溯源可以得出这样的依赖关系:roadhog 基于
umi/af-webpack
作为底层。从社区反馈的信息得知,现时(2019.1)作者的工作重点都在 umi,而 roadhog 无打算迭代升级的打算。即便将 roadhog 升级至最新版本,所依赖的底层 webpack 的版本也只是3.5.6,webpack4+ 的优化配置均无法使用。由于工具文档提供信息有限,因此要将优化进行到极致从源码依赖着手推动项目构建优化是免不了的工作。构建现况分析
分析材料
构建情况分析
项目构建优化方案
按照 Webpack 构建性能优化探索 提供的思路,可以从四个维度着手项目构建的优化:
去除废弃依赖
观察
package.json
,发现一些项目中废弃的依赖并没有及时处理,因此把无用的和重复安装的依赖去除。提取第三方公共模块
此前项目中页面代码根据路由按需加载,每个页面 route 和 model 引用的第三方模块,例如
react
、dva
、query-string
、antd
、moment
等,都会在各自的页面中重复打包一份,这就导致根据页面分割的资源文件尺寸较大,冗余代码较多。除此之外,值得注意的是,项目中使用的 AntDesign 组件,尽管通过 babel-plugin-import 实现了组件模块的按需加载,页面引用并不会将完整的 AntDesign 引入。但是由于开始时候大部分页面都不会从零开始写,而是会选择移植相似页面的逻辑再加以修改,因此会导致相当一部分页面会将没有使用到的组件进行打包,同样会造成冗余。
因此,整个项目的性能优化必然从资源依赖的第三方库着手,提前编译提取。
分析
package.json
可以得知整个项目依赖主要有几个部分:roadhog 暴露了 commons 参数对应 Webpack 中 plugins 的多个
webpack.CommonsChunkPlugin
实例。下面有两种可选择的方案供实现:最终决定将所有依赖的第三方模块提前打包,在用户访问页面时需要将基础工具和基础组件的打包文件先加载,后续用户界面资源文件加载就会相对另一种方案会更加快速。
相关扩展:
详解CommonsChunkPlugin的配置和用法
webpack.optimize.CommonsChunkPlugin 详解
webpack、manifest、runtime、缓存与CommonsChunkPlugin
第三方模块不同兼容库重复打包
vendor 提取第三方模块后,发现几个比较大的页面资源文件里仍然存在 antd.lib 组件库的代码,而且这些
ant.lib
都是完整一个模块被打包进了这些页面当中,但其实 AntDesign 已经被我完整单独地打包成另外一个文件了,这个打包的文件是由ant.es
打包出来的。通过对打包后的文件以及业务代码的检查,发现是引用 Antd 组件库发生了问题,由于使用了 webpack-plugin-import 插件,将 Antd 中名为 es 的组件库按需加载并通过 babel 转化独立打包成 vendor,因此当使用
import {message} from "antd/lib/index"
这种写法的时候,当前页面会将 Antd lib 目录下的组件全部打包,造成页面打包文件臃肿。书写规范
使用了 extraBabelPlugins 就会按需加载
忽略 moment 语言包的打包
打包后 moment 包的体积比较大,其中 locale 语言包部分占据了比较大的体积,由于我们的项目没有国际化需求,因此可以通过配置 roadhog 提供的
ignoreMomentLocale: true
减少打包出来的 vendor 尺寸。但是,如果项目中使用到 AntDesign 组件,并且使用到时间选择组件
date-picker
(默认是英文文案),那么这里需要做一些处理以使项目中组件能够显示中文。我是在项目最上层,单独引入 moment 的中文语言包。
这样项目中使用到 moment 工具库的
date-picker
都会显示中文文案。压缩耗时
项目构建过程会卡在91%,通过查阅相关资料和了解社区反馈后,明确原因为该阶段 Webpack 正在对代码进行混淆压缩操作,但同时由于 Webpack 的压缩插件 UglifyJS 无法对 ES6+ 的代码进行压缩,需要使用 babel-minify 获取更好的 treeshaking 效果(虽然 Webpack4 已经支持 ES6+ 代码压缩,但是目前 Roadhog 采用的是 Webpack3+)。
构建速度慢的解决方法@sorrycc
体现特征:
解决方法:
外部扩展
externals 是非常有效的一个方案,可以一下子减少大量需要编译、压缩的模块。将一些不常更新版本比较稳定的模块文件直接注入 HMTL 文件,当读取到该脚本时将自动加载,这不仅能加快构建速度,而且能够利用 CDN 进行资源缓存。
但是会带来的问题是:
使用 externals 需要在 HTML 里引用额外的 JS 文件,这里也有几个潜在的问题:
这里主要将三个尺寸较大且比较少项目页面引用的模块 externals 掉。
项目样式文件减少
ExtractTextPlugin 提取 CSS (antd + 业务)
能用公共就用公共(因为大部分的页面的样式几乎一样),不然每个页面开一个less引用公共,会重复打包,造成冗余。
Gzip传输压缩
gzip 需要在服务器配置开启
这里提供一种 Nginx 的配置。传送门
前端性能优化:gzip压缩文件传输数据
优化效果分析
后续需要解决的问题
单独打包的AntDesign尺寸过大
社区中有反应希望提取公共模块打包时将其中某些部分忽略不打包,而维护者似乎告知需要使用
babel-plugin-import
按需引用,并没提供提取公共模块的解决方案。 传送门参考资料
支持 vendor 的配置 Issue #370
roadhog2如何成功提取vendor · Issue #577
编译很慢 #722
roadhog 1.3x 打包慢的解决办法
Roadhog 构建优化
JS/CSS体积减少了67%,我们是如何做到的?
Webpack 日常使用与优化
The text was updated successfully, but these errors were encountered: