跳转至

📦 包体积与启动深度优化

包体积和启动速度是移动端最影响留存的两个指标(首屏每慢 1s 流失显著)。本篇讲:H5 拆包与 Tree-shaking、H5/小程序/原生 App 的启动链路、主线程长任务治理、TTI 优化、各框架专项。依据 web.dev 启动性能webpack/Rollup 官方小程序官方分包React Native Hermes/Flutter 官方。前置:性能专项监控与上线


一、指标定义(先统一口径)

指标 含义 参考阈值
FCP 首次内容绘制 < 1.8s
LCP 最大内容绘制 < 2.5s
TTI 可交互时间 < 3.9s
TBT 总阻塞时间(长任务累计) < 200ms
冷启动(原生) App 进程创建→首屏可交互 越低越好

TBT 反映主线程长任务影响,是 INP 的近亲(见 性能·INP)。


二、H5 包体积优化(前端可控)

2.1 路由级懒加载(最有效)

// Vue Router / React Router 用动态 import,拆分首屏
const Home = () => import('./pages/Home.vue')
const Detail = () => import('./pages/Detail.vue')

首屏只加载当前页 JS,其余按需。配合构建分析(rollup-plugin-visualizer)看谁占了体积。大厂首屏 JS 卡 < 200KB(见 监控·体积门禁 §5.1)。

2.2 Tree-shaking 与按需引入

// 错误:引入整个库
import _ from 'lodash'
// 正确:按需(或 lodash-es)
import debounce from 'lodash/debounce'
  • 用 ES Module("sideEffects": false 让打包器安全摇树)。
  • UI 库按需:vantunplugin-vue-components 自动按需;antd-mobile 同。

2.3 依赖治理

  • 删未用依赖;大库换小的(如 momentdayjslodash → 按需)。
  • compression(Brotli/gzip)减小传输体积(服务端/CDN 开)。

坑 1:polyfill 全量引入

@babel/preset-env 不配 useBuiltIns:'usage' → 打进全部 polyfill。改 usage 只补目标浏览器缺的(见 兼容性·babel §四),体积可省几十 KB。


三、启动链路与长任务治理

3.1 长任务(>50ms)是卡顿元凶

// 用 PerformanceObserver 抓长任务,定位卡点
new PerformanceObserver((list) => {
  for (const t of list.getEntries()) console.warn('Long Task', t.duration, t.startTime)
}).observe({ type: 'longtask', buffered: true })

治理手段: - 拆分:大循环分片(requestIdleCallback / setTimeout 切片)。 - 延迟:非首屏逻辑(埋点、预取)放到 requestIdleCallbackload 后。 - Web Worker:把重计算(解析/排序)丢 Worker,不占主线程(见 原生 API)。

3.2 首屏阻塞资源

  • JS 用 defer/type=module(默认 defer),别阻塞解析。
  • 关键 CSS 内联,非关键 CSS 异步加载。
  • 字体 font-display: swap,避免 FOIT 白字(见 性能·字体)。

四、小程序包体积(官方)

  • 主包 ≤ 2MB、整包 ≤ 20MB(官方硬限)。
  • 分包 + 独立分包 + 预下载(见 小程序原生开发 §三)。
  • 代码:用微信开发者工具"代码依赖分析"剔未引用;图片走 CDN 不出包。

坑 2:tabBar 图标/大图塞进包

图片是最大的包体积来源。tabBar 图标用合适尺寸(建议 81×81),其余图片全走 CDN。整包超 20MB 无法发布。


五、原生 App 启动优化(H5 嵌 WebView 场景)

5.1 冷启动链路

进程创建 → Application 初始化 → UI 创建 → WebView 初始化 → H5 加载 → 首屏可交互

优化点: - Application 初始化瘦身:SDK 懒加载/子线程初始化(推送、统计别全堆主线程)。 - WebView 预创建:App 启动就预热一个 WebView 实例池,进 H5 页直接复用,省初始化(数百 ms)。 - 离线包:H5 资源走本地(见 H5+WebView 离线包 §六),首屏秒开。

5.2 框架专项

框架 优化
React Native Hermes 引擎(字节码,启动快、内存低);启用 inlineRequires 懒加载模块
Flutter 减小基础包;用 --split-debug-info;避免过多 Opacity/大 Shader
uni-app(app-vue) nvue 页用原生渲染;离线打包 SDK 瘦身
纯 H5 见第二/三节

!!! tip "WebView 预创建是混合 App 首屏提速最大杠杆之一** 实测预热 WebView 可省 300-800ms。注意池大小控制内存(iOS 内存紧,池 1-2 个即可)。


六、防劣化(CI 卡门禁)

  • 构建后体积检查(首屏 chunk ≤ 阈值,见 监控 §5.1)。
  • Lighthouse CI 移动端分数门禁(性能/可访问性)。
  • 依赖变更审查:新增大依赖需评审。

七、速查:体积/启动问题 → 排查

现象 根因 方案
首屏 JS 大 未懒加载/全量引入 路由懒加载 + 按需
启动卡 主线程长任务 拆片/Worker/延迟
小程序传不上 主包>2MB/整包>20MB 分包 + 图片走 CDN
WebView 白屏久 未预热/无离线包 预创建 + 离线包
RN 启动慢 未开 Hermes 启用 Hermes

八、章节关联