本文作者: 李俊冬
使用 webpack 4 重构 yapi 构建脚本。
tl;dr
背景
我的一部分工作是基于 Yapi 做二次开发,Yapi 官方使用的构建工具是同属 YMFE 出品的 Ykit,Ykit 是基于 webpack@3.8.1 的二次封装,随着我开发强度的增加,Ykit 逐渐影响日常开发体验,尤其是 hot-reload 时间,而官方主要几乎停止维护,在看了 Ykit 源码之后,决定用 webpack@4.x 重写构建脚本。
升级 webpack@4.x
初始化配置
- 官方文档:webpack 官方文档有 V3 升级 V4 一些注意事项,其中就包括废弃的一些包
- 除了官方废弃的包,这次重构将 Babel 版本也升级到了 7.x,这个版本包都以命名空间的方式发布,所以需要重新安装
- webpack 基础配置,先配置 Dev 版
- 在进入 webpack 之前需要 initPlugin 生成一份插件列表 plugin-module.js,这部分代码沿用 ykit.config.js
- 配置 entry、output
- loader
- js loader
- css|sass|less|stylus loader,先上 style-loader 试试能不能跑通
- img|file loader
- plugin
- HtmlWebpackPlugin 生成入口页面
- 优化先跳过
- alias 配置沿用 ykit 的配置,common/client/exts
- dev server 配置
- 热更新
- 转发等 到这里升级就算结束了,webpack-dev-server --config ./config/webpack.dev.conf.js 没跑通,顺着报错挨个解决。
问题列表
Q1. babel-loader 无法识别 node_module 中的 React 代码
A: 通过配置 babel.config.js 或者 package.json 中的 babel 配置,不要使用 .babelrc ,参考
Q2: loader exclude 指定包
A: 这一点在 ykit.config.js 中有同样的配置,通过正则解决,示例如下
{
test: /\.js$/,
exclude: /node_modules\/(?!(MY-MODULE|ANOTHER-ONE)\/).*/,
},
Q3: tui-editor 的 icon 打包后,background 变成了 url([object Module])
A: 处理图片和字体的 loader 从 file-loader 更改为 url-loader
Q4: antd 打包 less 报错 .bezierEasingMixin()
A: less 版本降级到 3 以下解决
上面的问题解决之后,dev-server 可以跑通,接下来开始验证打包后的页面是否正常。
优化列表
- 使用 mini-css-extract-plugin 抽离样式:这种方式存在一个问题,在 yapi-plugin-wiki 插件的文档中,样式的引入顺序是先引入 codemirror 再引入 tui-editor,tui-editor 的样式文件复写了 codemirror 的部分样式,但 mini-css-extract-plugin 打包后的引用顺序不是源码的引入顺序,为了临时解决这个问题,只在 less 和 sass 这两种文件上使用 mini-css-extract-plugin,再回看 ykit.config.js 的配置,也是通过这种方式绕过。
- 分包:将一些低频变更的依赖打包,通过 contenthash 命名,避免每次上线后,用户需要重新下载所有包
- 使用 fast refresh 替代 react-hot-loader 实现热替换,具体方案可以参考 react-refresh-webpack-plugin,配置流程相较于 react-hot-loader 更简洁,流程大体为
- 依赖安装:npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
- webpack 的 plugins 在开发环境增加 new ReactRefreshWebpackPlugin()
- babel 的 plugins 在开发环境增加 react-refresh/babel
- 优化
- antd 按需加载
- moment.js 替换语言包
分包前
分包后
代码优化
可以进一步对依赖包进行瘦身,不过需要在代码中操作,下面是一些方向
- highlight.js 指定语言,避免引入全部语言包
- 使用 day.js 替换 moment.js
- 升级 antd@4.x 扔掉沉重的 icons/lib
总结
升级后
- 开发场景:实时预览热更新取代之前每次变更构建 10s+
- 生产构建:时间从 280s 降到 170s,降低 39%
符合 webpack 3 升级 4 的预期。