首屏渲染优化

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

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

精简初始 data

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

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

减少首屏节点数量

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

常用手段:

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

利用本地缓存

对于变化不频繁的首屏数据,采用"先缓存渲染,后台更新"的策略: 小程序提供 setStorage 和 getStorage 等本地缓存能力,数据存储在本地,返回速度快于网络请求。

  1. 上次请求成功后写入本地缓存
  2. 下次启动时先从缓存渲染
  3. 同时在后台发起请求获取最新数据
  4. 数据返回后更新视图
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 });
    });
  }, []);

  // ...
}

使用骨架屏

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

详见骨架屏生成方案。

小程序预加载

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

适合场景:首页投放卡片,点击唤起小程序。默认卡片会预下载小程序资源,当用户点击卡片时,会直接唤起小程序。

利用内存缓存

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

详见内存缓存。

检查清单

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