前段时间做了一个项目, 是使用 Create-React-App 脚手架 + TypeScript + Ant Design 组件库搭建的, 在减少包体积上有一些方法和大家分享一下. 我们目标是将包体积降到几十 k 这样一个级别上, 不受限于包体积, 坦然使用框架.
下文基于 webpack + TS 来说, 如果你的项目不在使用 TypeScript 的话可能会有些不一样, 但是思路是一致的; 文章比较简单, 如果遇到理解问题的话可以文章后面留言.
按需加载你的组件
比如我的项目中有个 modal, 用户不点击触发这个弹窗, 代码是不会被使用到的. webpack 原生就支持这种动态引入的写法
- export class YourComponent extends React.Component { onClick = () => { // 点击时才加载 Modal 相关的 js, 重命名这段 js 为 `modal123.hash.js`
- import('../Modal' /* webpackChunkName: 'modal123' */).then(Modal => {
- Modal.show()
- })
- }
- }
按需加载 ant design 组件
你当然可以通过如下的方式实现按需加载第三方组件. 这样做的话不会将整个组件库都打包进你的 js bundle, 只会将 Button 相关的代码打包进来
- // 方法 1
- import Button from 'antd/lib/button';
- import Menu from 'antd/lib/menu';
但是上述方法做显然不如下面来得方便和简洁. 但下面这样做却会将整个组件库打包进你的 js bundle 中, 显然是不能用于生产环境.
- // 方法 2
- import {Button, Menu} from 'antd';
为此 Ant design 提供了一个 webpack 插件 https://ant.design/docs/react/use-in-typescript-cn#%E4%BD%BF%E7%94%A8-ts-import-plugin , 使用了这个插件后就可以使用 方法 2 引入组件, 并在打包的时候按需加载.
less 自定义变量 + 按需加载 ant design 组件样式
在我们的项目中需要自定义 ant design 的组件样式, 你可以通过 自定义 less 变量 https://ant.design/docs/react/customize-theme-cn 的方式来实现你的自定义样式
- @import "~antd/dist/antd.less"; // 引入官方提供的 less 样式入口文件
- @primary-color: #2ca7fa;
但这样做的问题是, ant design 样式文件仍然是 "整包引入" 的, 我是通过如下方式按需加载的
- /**
- * 手动按需引入需要的 antd 样式
- *
- * based on node_modules/antd/lib/style/components.less
- */
- @import "../../node_modules/antd/lib/style/index.less";
- @import "../../node_modules/antd/lib/alert/style/index.less";
- @import "../../node_modules/antd/lib/button/style/index.less"; // 按需引入官方的基础样式, alert 样式, 按钮样式
- @primary-color: #2ca7fa;
外链 CSS
把 less 文件从 js bundle 中拆分出来, 减少 js bundle 体积, 预先加载 css
干掉 MomentJs
使用 dayjs 替换 momentjs. Ant design 的 LocaleProvider 中始终引用了整个 momentjs.
实际上下表中 moment 这个体积是包含了 locales 的, 本来就会把它删掉, 不会有那么多, 这里大概会减少 20kB 左右
library | minified and gzipped |
---|---|
moment | 64.2kB |
dayjs | 2.5kB |
source: https://bundlephobia.com/result?p=dayjs@1.7.4
如何使用 2kB 的 dayjs 来替换掉 64 kB 的 momentjs 呢, 这里用到是 webpack 的 alias
- module.exports = {
- resolve: {
- alias: {
- 'moment': 'dayjs',
- 'react': 'anujs',
- 'react-dom': 'anujs',
- },
- }
- }
减小 React 体积
业界有很多跟 React 保持一致 API 但是可能在兼容性, 包体积等方面有差异的类库 (React-like), 比如大名鼎鼎的 preact 在 gzip 之后只有 3kB. 我们可以选用包体积更小的类库, 和上述的 webpack alias 将 react 和 react dom 替换掉.
我们这里是使用 anujs 替换 react & react-dom. 截至目前, anujs 对 react 16 支持最好, preact, nervjs 等不支持 React Fragment, createPortal 等 API
但这里的风险是, 可能会导致兼容性问题: anujs 和 react 行为不一定一致, 所以在进行这一步替换之后, 务必进行详尽的测试. 不认为自己有能力把控风险的同学请谨慎操作.
来源: https://www.qcloud.com/developer/article/1159080