---
title: 代码注入优化
summary: "介绍代码注入阶段的优化方法，通过减少启动时必须执行的代码量来加快启动速度。"
docType: default
tags: [代码注入优化, 按需注入配置, 启动阶段代码加载]
questions:
  - 什么是代码注入阶段，它在启动流程中的作用是什么？
  - 模块顶层代码为什么会影响启动性能？
  - 如何将顶层的复杂计算改为懒执行？
  - 启动阶段哪些同步 API 有缓存机制？
  - 如何精简 App 初始化阶段的工作量？
  - app.tsx 中哪些逻辑应该延迟到首页组件挂载后执行？
---

# 代码注入优化

代码注入是小程序启动流程中继代码包下载后的关键阶段：基础库将开发者的 JS 代码加载进 JavaScript 引擎，依次完成解析、编译和执行。这个阶段的核心特点是——所有被加载模块的顶层代码都会在此刻立即执行，包括 `App()` 定义、全局变量初始化，以及 `App.onLaunch` / `App.onShow` 生命周期。

因此，优化代码注入耗时的核心思路是：**尽量减少启动时必须执行的代码量，将不紧迫的工作推迟到真正需要时再做**。

## 控制模块顶层的执行量

JS 模块的顶层代码（函数体以外的代码）在注入时会被立即执行。如果在顶层进行复杂计算、大量数据初始化或同步读取操作，这部分耗时会直接累加到注入阶段。

```javascript
// 顶层的 transform 调用在注入时立即执行
const processedList = rawList.map(item => heavyTransform(item));

// 推迟到真正需要时再处理
function getProcessedList() {
  if (!_cache) _cache = rawList.map(item => heavyTransform(item));
  return _cache;
}
```

## 减少同步 API 的调用

在启动过程中，高频调用 TTT 能力可能会阻塞 JS 线程，影响代码执行。应尽量减少或不调用同步 API，绝大多数同步 API 以 `Sync` 结尾。

**缓存机制:**

- 基础库对以下接口做了一层缓存，避免重复调用：
  - `getLaunchOptions`
  - `getLaunchOptionsSync`

- 以下接口调用频繁，但含有动态数据，无法直接缓存，可自行处理缓存：
  - `getSystemInfo`
  - `getSystemInfoSync`

> 注意：涉及 `system`、`brand`、`model`、`platform` 等数据可调用 [getDeviceInfo](/cn/miniapp/develop/miniapp/api/base/system/getDeviceInfo) 接口，该接口已做缓存

- 以下接口包含动态数据，暂不处理，业务层可自行缓存逻辑：
  - `getDeviceInfo`
  - `getGroupInfo`
  - `getCustomConfig`

> 非持久化存储可通过 `globalData` 存储，而非 `getStorage` 接口。

## 精简 App 初始化的工作量

Ray 项目的 `app.tsx` 在注入阶段会立即执行。常见误区是把所有初始化工作都集中在这里：

```tsx
// ❌ 避免：把不紧迫的逻辑堆在启动时执行
initSDK();         // 必要
checkLogin();      // 必要
loadUserConfig();  // 不紧迫，可延迟
reportAnalytics(); // 不紧迫，可延迟
checkAppUpdate();  // 不紧迫，可延迟
```

建议只保留真正影响首屏的逻辑（如登录态检查），其余操作延迟到首页组件挂载后再执行：

```tsx
// ✅ 推荐：非必要初始化推迟到首页挂载后
function HomePage() {
  useEffect(() => {
    loadUserConfig();
    reportAnalytics();
    checkAppUpdate();
  }, []);
}
```

## 检查清单

| 检查项 | 优化方法 |
| ------ | -------- |
| 模块顶层是否有复杂计算 | 改为懒执行，在需要时再计算 |
| 是否有大量同步 API 调用 | 减少或替换为异步 API，使用基础库缓存接口 |
| App 初始化是否包含非必要逻辑 | 延迟到首页组件挂载后再执行 |