Published on

punch 体积减小

Authors
  • avatar
    Name
    Magikarp
    Twitter

代码体积优化

现状

首屏加载

gzip 前为 1.8mb, gzip 后为 581kb

before

打包分析

gzip 前为 1.84mb

before-analyze

问题分析

  • 多个 UI 库
  • 多份 lodash
  • lodash 未按需加载
  • 含有可替代的包(moment, dva)
  • 非首屏加载 sdk(dingtalk-jsapi, sa-sdk-javascript),
  • 组件库未按需加载

下方所有体积缩小皆为 gzip 前的体积

antd-mobile 替换

去除项目中多个 ui 库的问题,使用内部的 sugar-design-mobile

体积缩小约 50kb

去除 antd

layout 文件中有历史原因遗留的 antd,替换为 sugar-design-mobile

体积缩小约 100kb

使用 dayjs 替换 moment

常规操作,dayjs 体积更小。

体积缩小约 50kb

lodash 重复打包问题

不同的 lodash 版本会导致重复打包,通过 alias 的方式将版本统一。

体积缩小约 70kb

sugar-design-mobile 支持按需加载

部分 api 未适配,需要手动适配。

体积缩小约 110kb

dingtalk-api 非必须

在非钉钉的环境中并不需要 dingtalk api, 应该更改为按需加载即可。

非钉钉场景下首屏体积减小 200kb

lodash 同时存在全量包及子包

同时打入了全量的 lodash 及子包,相当于打包了两次。

需要修改 sirius 及 sugar-design-mobile 的 lodash 引用及打包方式。

现状:

// 打包前:
import { omit } from 'lodash'

// 打包后:
const _ = require('lodash') // 全量引入
const omit = lodash.omit

解决方法:

  1. lodash/omit
import omit from 'lodash/omit'
  1. babel-plugin-import
// 打包前:
import { omit } from 'lodash'
// 打包后
const omit = require('lodash/omit')

// 打包前:
import _ from 'lodash' // 全量引入,这种需要避免
const omit = _.omit
// 打包后
const _ = require('lodash') // 全量引入
const omit = _.omit

体积缩小约 50kb

使用 zustand 替换为 dva

zustand 拥有体积更小,ts 支持度更高,api 更简洁的优点,具体可以阅读 dva 阵痛迁移至 zustand

sa-sdk-javascript 异步加载

注意 使用异步加载后如果开启了全埋点,则在加载 sdk 成功前的点击事件不会记录。

首屏体积缩小约 159kb

较为激进的优化

sa-sdk-javascript 在发送埋点前再调用

因该项目未开启全埋点,所以延迟注册,在使用的时候再将 sdk 引入。

首屏体积缩小约 159kb

vconsole 按需加载

目前 vconsole 不管在什么条件下都会优先进行加载,考虑将其作为某种特殊场景触发后再进行加载的异步产物。

按照目前的逻辑,可以考虑的逻辑为:

  1. 点击二次增加 flag 然后加载 vconsole, 初始化 vconsole。
  2. 进入页面时判断 flag 加载 vconsole
  3. 增加 flag 有效期

伪代码环节:

<script>
  window.addEventListener(
    'load',
    (e) => {
      document.body.addEventListener('click', () => {
        // 某种条件触发
        localStorage.setItem('load-vconsole', true)
      })
    },
    false
  )
</script>
<script>
  // 加载 vconsole
  if (localStorage.getItem('load-vconsole')) {
    document.write('<script src="./vconsole.js" />')
  }
</script>

首屏体积缩小约 94kb

lark/h5jssdk 按需加载

dingtalk-api 相同,除了飞书环境外都不需要使用,目前是通过 script 加载的,通过 document.write 配合 ua 来进行按需加载

if (!!navigator.userAgent.match(/Lark/)) {
  document.write(
    '<script src="https://lf1-cdn-tos.bytegoofy.com/goofy/ee/lark/h5jssdk/lark/js_sdk/h5-js-sdk-1.5.8.js" />'
  )
}

首屏体积缩小约 234kb

wechat work jssdk 按需加载

同上

const u = navigator.userAgent.toLowerCase()
const isWorkWeiXin = !!u.match(/wxwork/)
if (isWorkWeiXin) {
  document.write('<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" />')
}

首屏体积缩小约 11.6kb

优化后

webpack analyze

gzip 前为 1.31mb

before-analyze

首屏体积

before 2.5mb, gzip 769kb

network-before

after 1.3mb, gzip 422kb (~45.12%) (vconsole 在生产环境不在默认加载,此处模拟生产环境)

network-after

可能还能干的事情

  • @umi/core-js