# 首屏渲染优化

页面首屏渲染的优化，目的是让「首页渲染完成」(`Page.onReady`) 尽可能提前。但很多情况下「首页渲染完成」可能还是空白页面，因此更重要的是让用户能够更早的看到页面内容（First Paint 或 First Contentful Paint）。

## 1. 使用「[按需注入](../../ability/lazyload#按需注入)」和「[用时注入](../../ability/lazyload#用时注入)」

除了优化代码注入的耗时外，「按需注入」和「用时注入」也可以减少需要初始化的组件数量，降低实际页面渲染的耗时，使「首页渲染完成」提前。

> 启用「按需注入」之后，部分组件代码注入会被延迟到首页渲染阶段执行，导致阶段耗时上涨，但总耗时一般会下降。

## 2. 启用「[初始渲染缓存](/miniprogram/dev/framework/view/initial-rendering-cache)」

自基础库版本 2.11.1 起，小程序支持启用**初始渲染缓存**。开启后，可以在**非首次**启动时，使视图层不需要等待逻辑层初始化完毕，而直接提前将页面渲染结果展示给用户，这可以使「首页渲染完成」和页面对用户可见的时间大大提前。

## 3. 避免引用未使用的自定义组件

在页面渲染时，会初始化在当前页面配置和全局配置通过 `usingComponents` 引用的自定义组件，以及组件所依赖的其他自定义组件。未使用的自定义组件会影响渲染耗时。

当组件不被使用时，应及时从 `usingComponents` 中移除。

## 4. 精简首屏数据

首页渲染的耗时与页面的复杂程度正相关。对于复杂页面，可以选择进行渐进式的渲染，根据页面内容优先级，优先展示页面的关键部分，对于非关键部分或者不可见的部分可以延迟更新。

此外，与视图层渲染无关的数据应尽量不要放在 data 中，避免影响页面渲染时间。

## 5. 提前首屏数据请求

很多小程序在渲染首页时，需要依赖服务端的接口数据（如商品列表等），此时小程序的首页可能是空白或者骨架屏。

由于网络请求需要相对较长的时间，我们建议开发者在 `Page.onLoad` 或更早的时机发起网络请求，而不应等待 `Page.onReady` 之后再进行。

为了进一步提前请求发起的时机，小程序为开发者提供了以下能力：

- [数据预拉取](/miniprogram/dev/framework/ability/pre-fetch)：能够在小程序冷启动时，由微信客户端通过微信后台提前向第三方服务器拉取业务数据，当代码包加载完时可以更快地渲染页面，减少用户等待时间。
- [周期性更新](/miniprogram/dev/framework/ability/background-fetch)：在用户未打开小程序的情况下，也能从服务器提前拉取数据，当用户打开小程序时可以更快地渲染页面，减少用户等待时间。

## 6. 缓存请求数据

小程序提供了[wx.setStorage](/miniprogram/dev/api/storage/wx.setStorage.md)、[wx.getStorage](/miniprogram/dev/api/storage/wx.getStorage.md)等读写本地缓存的能力，数据存储在本地，返回的会比网络请求快。如果开发者基于某些原因无法采用数据预拉取与周期性更新，我们推荐优先从缓存中获取数据来渲染视图，等待网络请求返回后进行更新。

## 7. 骨架屏

骨架屏通常用于在页面完全渲染之前，通过一些灰色的区块大致勾勒出轮廓，待数据加载完成后，再替换成真实的内容。

建议开发者在页面数据未准备好时（例如需要通过网络获取），尽量避免展示空白页面，而是先通过骨架屏展示页面的大致结构，请求数据返回后再进行页面更新。以提升用户的等待意愿。

开发者工具提供了[生成骨架屏](/miniprogram/dev/devtools/skeleton.md)的能力，帮助开发者更便捷的维护骨架屏。

![](https://res.wx.qq.com/wxdoc/dist/assets/img/progressiveLoad.722964c8.gif)
