前段时间做了一个项目,是使用 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()
})
}
}
你当然可以通过如下的方式实现按需加载第三方组件。这样做的话不会将整个组件库都打包进你的 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 插件 ts-import-plugin, 使用了这个插件后就可以使用 方法2
引入组件,并在打包的时候按需加载。
在我们的项目中需要自定义 ant design 的组件样式,你可以通过 自定义 less 变量 的方式来实现你的自定义样式
@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;
把 less 文件从 js bundle 中拆分出来,减少 js bundle 体积,预先加载 css
使用 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 保持一致 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行为不一定一致,所以在进行这一步替换之后,务必进行详尽的测试。不认为自己有能力把控风险的同学请谨慎操作。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。