---
title: 首屏渲染优化
summary: "介绍首屏渲染优化方法，包括精简初始数据、利用本地缓存和骨架屏等策略。"
docType: default
tags: [首屏渲染优化, 首屏数据缓存, 初始渲染加速方案]
questions:
  - 首屏渲染阶段的耗时主要来自哪些方面？
  - 如何精简初始 data 以加快首屏渲染？
  - 减少首屏节点数量有哪些常用手段？
  - 如何利用本地缓存实现先缓存渲染后台更新的策略？
  - preDownloadMiniApp 和 preloadPanel 的预加载机制是什么？
  - 小程序的内存缓存机制如何加快二次打开速度？
  - 首屏白屏时间长应该如何排查和优化？
---

# 首屏渲染优化

代码注入完成后，小程序进入首屏渲染阶段：`Page.onLoad` 触发、组件树初始化、初始数据传输到视图层、视图层完成渲染，直到 `Page.onReady` 触发为止。

这个阶段的耗时主要来自两个方向：**渲染本身的复杂度**（节点数量、数据量大小），以及**数据的等待时间**（网络请求、本地读取）。两者都会影响用户看到可用内容的时机。

## 精简初始 data

`data` 中的数据在每次渲染前都会从逻辑层传输到视图层，首屏 `data` 的大小直接影响传输耗时和渲染耗时。

- **放了首屏用不到的数据**：数据分页、Tab 切换内容、弹窗内容等不在首屏展示，如果提前放入 `data` 初始值，会参与传输和渲染计算。应在需要展示时才通过 `setData` 更新。
- **把非渲染数据放进了 data**：逻辑计算的中间结果、配置项、静态映射表等与视图无关的数据，放在 `data` 里只会增加传输负担。应挂在 `this` 上作为普通属性。

## 减少首屏节点数量

页面节点数越多，视图层的布局计算和绘制开销越大。

**常用手段**：

- **条件渲染延迟展示**：屏幕外的区域（如折叠内容、底部区块）首屏渲染完成后再展示
- **长列表分页渲染**：首屏只渲染前几条数据，用户滚动时再追加
- **延迟挂载非必需组件**：过多的自定义组件会增加初始化开销，非首屏必需的组件可以延迟挂载


## 利用本地缓存

对于变化不频繁的首屏数据，采用"先缓存渲染，后台更新"的策略：
小程序提供 [setStorage](/cn/miniapp/develop/ray/api/storage/setStorage) 和 [getStorage](/cn/miniapp/develop/ray/api/storage/getStorage) 等本地缓存能力，数据存储在本地，返回速度快于网络请求。

1. 上次请求成功后写入本地缓存
2. 下次启动时先从缓存渲染
3. 同时在后台发起请求获取最新数据
4. 数据返回后更新视图


```tsx
import { getStorage, setStorage } from '@ray-js/ray';

function HomePage() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 先读缓存渲染
    getStorage({
      key: 'panelData',
      success: (res) => setData(res.data),
    });

    // 后台获取最新数据
    fetchPanelData().then((fresh) => {
      setData(fresh);
      setStorage({ key: 'panelData', data: fresh });
    });
  }, []);

  // ...
}
```

## 使用骨架屏

即使做了请求提前和缓存优化，仍有部分数据需要等待。骨架屏可以在数据返回前展示页面的大致轮廓，让用户感知到"页面在加载"而非"页面没有响应"，降低感知等待时间。

详见[骨架屏生成方案](/cn/miniapp/develop/ray/guide/optimization/experience/skeleton)。

## 小程序预加载

对于通过卡片或快捷入口打开的小程序，可以调用 [preDownloadMiniApp](/cn/miniapp/develop/ray/api/base/container/preDownloadMiniApp#predownloadminiapp) 和 [preloadPanel](/cn/miniapp/develop/ray/api/base/panel/preloadPanel#preloadpanel) 提前在后台完成代码包下载。用户真正点击时跳过下载阶段直接进入注入流程，首次打开体验会明显更快。
默认投放的首页卡片已内置预下载逻辑，无需额外配置。

**适合场景**：首页投放卡片，点击唤起小程序。默认卡片会预下载小程序资源，当用户点击卡片时，会直接唤起小程序。
## 利用内存缓存

小程序关闭后短时间内重新进入，基础库的内存缓存机制可以跳过下载和部分注入步骤，加快重新打开的速度。这一能力默认开启，没有特殊需求不要关闭。

详见[内存缓存](/cn/miniapp/develop/ray/guide/ability/memoryCache)。

## 检查清单

| 问题现象 | 可能原因 | 优化方法 |
| -------- | -------- | -------- |
| 首屏渲染耗时长 | 初始 data 包含非首屏字段，传输数据量过大 | 只保留首屏渲染必需的字段，其余数据按需加载 / 延迟加载 |
| 页面布局计算慢、绘制卡顿 | 首屏节点数过多 | 折叠区块、列表等改为条件渲染或分页渲染，首屏只渲染可见部分 |
| 首屏内容等待网络才能展示 | 每次启动都依赖网络请求返回后才渲染 | 对于不易改动的数据，读取本地缓存先渲染，同时后台请求并更新视图 |
| 用户感知白屏时间长 | 数据加载期间页面无任何内容 | 加入骨架屏，在数据返回前展示页面轮廓 |
| 卡片点击后首次打开慢 | 点击时才开始下载代码包 | 调用 `preDownloadMiniApp` / `preloadPanel` 提前在后台下载 |
| 二次打开速度明显变慢 | 内存缓存被关闭，跳过了缓存加速路径 | 确认未关闭内存缓存，恢复默认配置 |
