Taro-05-分包策略

包体积过大?我会这样教你「先诊断、再分包、再治理」

顶级前端不会一上来就改配置,而是先建立一套可复用的思维框架。

一、先建立正确目标:你在优化什么?

包体积不是单一数字,要分三层看:

指标 含义 典型目标
首包体积 用户第一次打开必须下载的 JS H5 < 200KB gzip;小程序主包 < 2MB
首屏 JS 首屏渲染真正执行的代码 越小越好,通常 < 100KB
总包体积 全站所有 chunk 之和 可以大,但不能阻塞首屏

核心原则:

不是把包拆小,而是把「用户现在不需要的代码」推迟加载。


二、我的工作流:Measure → Analyze → Split → Verify → Guard
三、诊断工具(按平台)

可视化分析(Vite 用 rollup-plugin-visualizer):

TypeScript 复制代码
// config/prod.ts
export default {
  compiler: {
    type: 'vite',
    vitePlugins: [visualizer({ open: true, gzipSize: true, brotliSize: true })],
  },
},
四、分包的 4 种手段(从易到难)
1. 按页面拆包(最常用,ROI 最高)

antd、echarts、富文本编辑器等重库不要在入口文件、app.ts 或公共 layout 里引入

2. 小程序「分包」(subPackages)

这是微信小程序特有的「物理分包」,和 H5 的 code splitting 是两套机制。

TypeScript 复制代码
// src/app.config.ts
export default defineAppConfig({
  pages: [
    'pages/index/index',      // 主包:Tab 页、登录、高频页
  ],
  subPackages: [
    {
      root: 'packages/order',
      pages: ['list/index', 'detail/index'],
    },
    {
      root: 'packages/user',
      pages: ['profile/index', 'settings/index'],
    },
  ],
  preloadRule: {
    'pages/index/index': {
      network: 'all',
      packages: ['packages/order'], // 首页预下载 order 分包
    },
  },
})

分包设计原则:

  1. 主包 = 启动路径 + TabBar 页 + 公共组件/工具(尽量轻)
  2. 分包 = 按业务域划分(订单、用户、活动、管理后台...)
  3. 独立分包 = 可被分享直达、不依赖主包的页面(如活动落地页)

目录结构示例:

src

├─ pages

│ └─ index ← 主包

└─ packages

├─ order

│ ├─ list

│ └─ detail

└─ user

└─ profile


3. Vendor 拆分(第三方库隔离)

H5 端可在 Vite 配置 manualChunks

TypeScript 复制代码
// config/prod.ts
import type { UserConfigExport } from '@tarojs/cli';

export default {
  mini: {},
  modifyViteConfig(viteConfig) {
    const output = viteConfig.build?.rollupOptions?.output;
    if (Array.isArray(output)) return;

    viteConfig.build = {
      ...viteConfig.build,
      rollupOptions: {
        ...viteConfig.build?.rollupOptions,
        output: {
          ...(typeof output === 'object' ? output : {}),
          manualChunks(id: string) {
            if (id.includes('node_modules')) {
              if (id.includes('react')) return 'vendor-react';
              if (id.includes('@tarojs')) return 'vendor-taro';
              if (id.includes('antd')) return 'vendor-antd';
              return 'vendor';
            }
          },
        },
      },
    };
  },
  h5: {},
} satisfies UserConfigExport<'vite'>;

这是 Rollup 的 output.manualChunks 钩子(Vite 生产构建底层用 Rollup):

  • 构建时 Rollup 遍历每个模块,把模块的文件路径传给你
  • return 一个字符串 = 这个模块打进哪个 chunk
  • 返回 undefined / 不 return = 交给 Rollup 默认策略

4. 组件/功能级动态加载

适合:编辑器、地图、PDF 预览、复杂图表等「低频重功能」。

TypeScript 复制代码
import { lazy, Suspense } from 'react'

const RichEditor = lazy(() => import('@/components/RichEditor'))

function Page() {
  const [showEditor, setShowEditor] = useState(false)

  return (
    <>
      <Button onClick={() => setShowEditor(true)}>写评论</Button>
      {showEditor && (
        <Suspense fallback={<Loading />}>
          <RichEditor />
        </Suspense>
      )}
    </>
  )
}

顶级细节:

  • Suspense 提供 fallback,避免白屏
  • 可配合 import(/* webpackPrefetch: true */ ...) 在用户 hover 时预加载
  • 小程序端动态 import 支持有限,优先用 分包 + 独立页面 代替

五、比「分包」更底层的减体积手段

分包是「推迟加载」;下面这些才是「真正变小」:

1. 按需引入(Tree Shaking 的前提)
TypeScript 复制代码
// ❌
import _ from 'lodash'
// ✅
import debounce from 'lodash/debounce'

// ❌ antd 全量
import { Button, Modal, Table } from 'antd'
// ✅ 若项目配置了 babel-plugin-import 或 antd 5 的 ES module,确保走 ESM 路径
2. 检查 package.json 的 sideEffects
TypeScript 复制代码
{
  "sideEffects": ["*.scss", "*.css"]
}

没有 sideEffects 标记,打包器可能不敢 tree-shake。

3. 替换重依赖
moment.js dayjs
lodash 全量 lodash-es + 按需
echarts 全量 按需 register 图表类型
axios(若只用 Taro.request) 直接用 @tarojs/taro request
4. 图片/字体/静态资源
  • 大图走 CDN + WebP/AVIF
  • 图标用 SVG sprite 或 iconfont 子集,不要引整套 icon 库
  • 字体只打包用到的字重
相关推荐
weixin_471383033 小时前
Taro-04-网络请求
前端·javascript·taro
Geek_Vison1 天前
2026 跨端框架横评:FinClip、Taro、uni-app、Remax、mPaaS 五款工具技术+业务双维度测评
小程序·uni-app·taro·mpaas·小程序容器
喵个咪10 天前
基于 Taro 的 Headless CMS 多端前端架构:技术解析与二次开发导引
前端·react.js·taro
Dragon Wu1 个月前
Taro v4.2.0 scss使用“@/xxx“的配置方法
前端·小程序·taro·scss
朱良1 个月前
Taro小程序生成分享海报解决方案
taro
代码不加糖1 个月前
从零手写简易 Taro:20 行 JSX 如何变成小程序?(硬核实战)
小程序·taro
lichenyang4532 个月前
从零到一:用 Taro + React 搭建数据采集小程序
react.js·小程序·taro
今天不要写bug2 个月前
Taro小程序微信、支付宝双端实现二维码图片生成
微信·小程序·taro
喵了几个咪2 个月前
Headless 架构优势:内容与展示解耦,一套 API 打通全端生态
vue.js·架构·golang·cms·react·taro·headless