🔧 Expo 迁移故障排除与学习总结

📋 文档概述

本文档记录了从 React Native CLI 项目迁移到 Expo Bare Workflow 过程中遇到的所有问题、解决方案和学习要点,供未来参考和复盘使用。

项目背景:

  • 原项目:React Native 0.71.10 + 复杂原生模块(RFID功能)
  • 目标:Expo SDK 50 Bare Workflow
  • 迁移时间:2025年7月23日

🚀 完整迁移步骤与方案

阶段1:项目分析与准备

1.1 原项目结构分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
原项目结构 (App/):
├── app/                    # 主要应用代码
│   ├── App.tsx            # 应用入口
│   ├── components/        # 组件库
│   ├── navigation/        # 导航配置
│   ├── redux/            # 状态管理
│   └── ...
├── android/              # Android 原生代码
│   └── app/src/main/java/com/inventory/
│       ├── RFIDWithUHFUARTModule.java  # RFID UART 模块
│       └── RFIDWithUHFBLEModule.java   # RFID BLE 模块
├── ios/                  # iOS 原生代码
└── package.json          # 依赖配置

1.2 关键依赖识别

原始关键依赖:

1
2
3
4
5
6
7
8
{
  "react-native": "0.71.10",
  "react-native-quick-sqlite": "^8.0.0-beta.2",
  "react-native-fs": "^2.20.0",
  "react-native-vision-camera": "^2.15.4",
  "@react-navigation/native": "^6.1.0",
  "react-redux": "^8.0.5"
}

需要迁移的模块:

  • react-native-quick-sqliteexpo-sqlite
  • react-native-fsexpo-file-system
  • react-native-vision-cameraexpo-camera

阶段2:新项目创建与基础配置

2.1 创建 Expo Bare Workflow 项目

1
2
3
4
# 在 Inventory 根目录下创建新项目
npx create-expo-app InventoryExpo --template bare-minimum

cd InventoryExpo

2.2 核心配置文件设置

app.json 配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
  "expo": {
    "name": "Inventory",
    "slug": "inventory-app",
    "version": "0.0.1",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "automatic",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "vg.zeta.app.inventory",
      "buildNumber": "1"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      },
      "package": "vg.zeta.app.inventory",
      "versionCode": 1
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

eas.json 构建配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "cli": {
    "version": ">= 7.8.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  },
  "submit": {
    "production": {}
  }
}

metro.config.js 配置:

1
2
3
4
5
const { getDefaultConfig } = require('@expo/metro-config');

const config = getDefaultConfig(__dirname);

module.exports = config;

babel.config.js 配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
  presets: ['babel-preset-expo'],
  plugins: [
    'macros',
    [
      'react-native-reanimated/plugin',
      {
        // globals: ['__scanCodes'],
      },
    ],
    [
      'module-resolver',
      {
        root: ['./'],
        alias: {
          '@app': './app',
          '@deps': './deps',
        },
      },
    ],
  ],
};

2.3 依赖安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 安装 Expo SDK 50 核心依赖
npm install expo@~50.0.0

# 安装替代模块
npm install expo-sqlite@~13.0.0
npm install expo-file-system@~16.0.0
npm install expo-camera@~14.0.0

# 安装其他必要依赖
npm install expo-status-bar@~1.11.0
npm install expo-splash-screen@~0.26.0

# React Navigation
npm install @react-navigation/native@^6.1.0
npm install @react-navigation/native-stack@^6.9.0
npm install @react-navigation/stack@^6.3.0

# React Native 兼容包
npm install react-native-safe-area-context@4.6.3
npm install react-native-screens@~3.22.0
npm install react-native-gesture-handler@~2.12.0

# Web 支持
npm install react-native-web@~0.19.6
npm install react-dom@18.2.0
npm install @expo/metro-runtime@~3.1.3

# 开发依赖
npm install --save-dev @babel/core@^7.20.0
npm install --save-dev babel-preset-expo@~9.5.0
npm install --save-dev @tsconfig/react-native@^3.0.6
npm install --save-dev typescript@^5.1.3
npm install --save-dev babel-plugin-macros@^3.1.0

阶段3:代码迁移策略

3.1 自动化迁移脚本创建

创建批处理脚本 (migrate-code.bat):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@echo off
chcp 65001 > nul
echo 正在迁移应用代码...

robocopy "..\App\app" "app" /E /XD node_modules .git
robocopy "..\App\deps" "deps" /E /XD node_modules .git

echo 正在复制原生模块...
robocopy "..\App\android\app\src\main\java" "android\app\src\main\java" /E
robocopy "..\App\ios" "ios" *.h *.m *.mm /S

echo 代码迁移完成!
pause

3.2 资源文件处理

1
2
3
4
5
# 复制并调整图标文件
cp ../App/android/app/src/main/res/mipmap-hdpi/ic_launcher.png assets/icon.png
cp ../App/android/app/src/main/res/mipmap-hdpi/ic_launcher.png assets/adaptive-icon.png
cp ../App/android/app/src/main/res/mipmap-hdpi/ic_launcher.png assets/splash.png
cp ../App/android/app/src/main/res/mipmap-hdpi/ic_launcher.png assets/favicon.png

3.3 入口文件适配

index.js (Expo 入口):

1
2
3
4
5
import { registerRootComponent } from 'expo';
import App from './App';

// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
registerRootComponent(App);

App.js (简化版本):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Platform } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Inventory App (Expo)</Text>
      <Text style={styles.subtitle}>迁移成功</Text>
      <Text style={styles.platform}>Platform: {Platform.OS}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 20,
  },
  // ... 其他样式
});

阶段4:原生项目生成与配置

4.1 生成原生项目

1
2
3
4
5
6
# 生成 Android 和 iOS 项目
npx expo prebuild

# 验证生成结果
ls android/  # 应该看到 Android 项目结构
ls ios/      # 应该看到 iOS 项目结构

4.2 原生模块集成

Android 模块集成:

  1. 复制 RFID 模块文件到正确位置
  2. 更新 android/settings.gradle
  3. 更新 android/app/build.gradle
  4. 注册模块到 MainApplication.java

iOS 模块集成:

  1. 复制 .h.m 文件
  2. 更新 ios/Podfile
  3. 运行 cd ios && pod install

阶段5:API 迁移与适配

5.1 数据库 API 迁移

原始代码 (react-native-quick-sqlite):

1
2
3
import { open } from 'react-native-quick-sqlite';
const db = open({ name: 'mydb.db' });
db.execute('SELECT * FROM items');

迁移后 (expo-sqlite):

1
2
3
4
5
6
7
import * as SQLite from 'expo-sqlite';
const db = SQLite.openDatabase('mydb.db');
db.transaction(tx => {
  tx.executeSql('SELECT * FROM items', [], (_, results) => {
    // 处理结果
  });
});

5.2 文件系统 API 迁移

原始代码 (react-native-fs):

1
2
import RNFS from 'react-native-fs';
RNFS.writeFile(path, data, 'utf8');

迁移后 (expo-file-system):

1
2
import * as FileSystem from 'expo-file-system';
FileSystem.writeAsStringAsync(uri, data);

5.3 相机 API 迁移

原始代码 (react-native-vision-camera):

1
import { Camera } from 'react-native-vision-camera';

迁移后 (expo-camera):

1
import { Camera } from 'expo-camera';

阶段6:测试与验证

6.1 基础功能测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 启动开发服务器
npx expo start

# Android 测试
npx expo run:android

# iOS 测试
npx expo run:ios

# Web 测试
npx expo start --web

6.2 原生模块测试

1
2
3
4
5
6
7
8
// 测试 RFID 模块是否正常工作
import { NativeModules } from 'react-native';
const { RFIDWithUHFUARTModule } = NativeModules;

// 测试模块调用
RFIDWithUHFUARTModule.testConnection()
  .then(result => console.log('RFID 模块工作正常:', result))
  .catch(error => console.error('RFID 模块错误:', error));

阶段7:生产构建准备

7.1 EAS 构建配置

1
2
3
4
5
6
7
8
# 安装 EAS CLI
npm install -g @expo/eas-cli

# 配置构建
eas build:configure

# 构建测试版本
eas build --platform android --profile preview

7.2 代码签名与发布准备

  • Android: 配置 keystore
  • iOS: 配置 provisioning profiles
  • 更新应用图标和启动画面

🎯 迁移方案选择与决策

方案对比分析

方案A:Expo Managed Workflow

优点:

  • 开发体验最佳
  • 无需管理原生代码
  • OTA 更新简单

缺点:

  • 无法使用自定义原生模块
  • ❌ 不支持现有的 RFID 模块

决策: ❌ 不可行 - 由于项目依赖自定义 RFID 原生模块

方案B:Expo Bare Workflow (选择的方案)

优点:

  • ✅ 保留自定义原生模块支持
  • ✅ 享受 Expo 开发工具链
  • ✅ 支持 EAS 构建和更新
  • ✅ 兼容现有 React Native 代码

缺点:

  • 需要管理原生项目
  • 配置相对复杂

决策: ✅ 最佳选择 - 平衡了功能需求和开发体验

方案C:保持 React Native CLI

优点:

  • 无需迁移
  • 完全兼容现有代码

缺点:

  • 错过 Expo 生态系统优势
  • 开发和构建流程复杂

决策: ❌ 不推荐 - 无法享受 Expo 的现代化开发体验

技术栈选择说明

Expo SDK 版本选择

  • 选择: Expo SDK 50
  • 原因:
    • 支持 React Native 0.72.x
    • 满足 Android API 34+ 要求(Google Play 新要求)
    • 长期支持版本

依赖替换策略

原始依赖 Expo 替代方案 迁移难度 功能对比
react-native-quick-sqlite expo-sqlite 功能相当,API 略有差异
react-native-fs expo-file-system 功能受限但满足基本需求
react-native-vision-camera expo-camera 功能简化,需要重写相机逻辑
react-native-image-picker expo-image-picker API 相似,易于迁移

🚨 主要问题分类

1. 依赖冲突问题

问题1.1: babel-plugin-macros 缺失

1
ERROR: Cannot find module 'babel-plugin-macros'

原因分析:

  • Babel 配置中使用了 ‘macros’ 插件但未安装依赖
  • Metro bundler 在转换代码时找不到对应的插件

解决方案:

1
npm install babel-plugin-macros --save-dev

学习要点:

  • Expo 项目的 Babel 配置需要确保所有插件都正确安装
  • babel-plugin-macros 是处理编译时宏的重要工具

问题1.2: TypeScript 配置缺失

1
ERROR: Cannot find module '@tsconfig/react-native'

解决方案:

1
npm install @tsconfig/react-native --save-dev

学习要点:

  • Expo 推荐使用预设的 TypeScript 配置
  • 这个包提供了 React Native 项目的最佳实践配置

2. 权限与安全问题

问题2.1: Android 权限拒绝错误

1
ERROR: Permission Denial: registerScreenCaptureObserver requires android.permission.DETECT_SCREEN_CAPTURE

尝试的解决方案:

  1. 方案A: 添加权限到 app.json
1
2
3
4
5
6
7
{
  "android": {
    "permissions": [
      "android.permission.DETECT_SCREEN_CAPTURE"
    ]
  }
}
  1. 方案B: 移除有问题的插件
1
2
3
{
  "plugins": []
}
  1. 方案C: 简化权限列表
1
2
3
4
5
6
7
8
{
  "android": {
    "permissions": [
      "android.permission.INTERNET",
      "android.permission.ACCESS_NETWORK_STATE"
    ]
  }
}

问题持续原因:

  • 某些 Expo SDK 模块在初始化时会尝试注册系统级观察者
  • 这些操作需要特殊的系统权限,不是普通应用权限能解决的

学习要点:

  • Android 权限分为普通权限和特殊权限
  • 某些 Expo 模块可能有隐式的权限要求
  • 权限问题需要从源头(依赖选择)解决,而不仅仅是配置

3. 应用注册问题

问题3.1: AppRegistry 注册失败

1
2
3
ERROR: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called

原因分析:

  • 应用入口点配置问题
  • 某个模块加载失败导致 AppRegistry.registerComponent 未被调用
  • Metro bundler 可能从错误的目录运行

解决方案:

  1. 确保正确的入口文件 (index.js):
1
2
3
4
import { registerRootComponent } from 'expo';
import App from './App';

registerRootComponent(App);
  1. 简化 App.js 避免复杂依赖:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Platform } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Inventory App (Expo)</Text>
      <Text style={styles.subtitle}>迁移成功</Text>
      <Text style={styles.platform}>Platform: {Platform.OS}</Text>
      <StatusBar style="auto" />
    </View>
  );
}
  1. 清理缓存重新构建:
1
2
npx expo start --clear
npx expo prebuild --clean

学习要点:

  • Expo 使用 registerRootComponent 而不是直接使用 AppRegistry
  • 应用入口必须足够简单,避免在初始化阶段加载复杂模块
  • 缓存问题经常导致注册失败

实际执行的命令记录

项目创建阶段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 1. 创建新的 Expo 项目
npx create-expo-app InventoryExpo --template bare-minimum

# 2. 进入项目目录
cd InventoryExpo

# 3. 安装核心依赖
npm install expo@~50.0.0
npm install expo-sqlite@~13.0.0 expo-file-system@~16.0.0 expo-camera@~14.0.0
npm install expo-status-bar@~1.11.0 expo-splash-screen@~0.26.0
npm install react-native-web@~0.19.6 react-dom@18.2.0
npm install @expo/metro-runtime@~3.1.3

代码迁移阶段

1
2
3
4
5
6
7
8
9
# 4. 复制原始代码(使用批处理脚本)
migrate-code.bat

# 5. 安装开发依赖
npm install --save-dev @babel/core@^7.20.0
npm install --save-dev babel-preset-expo@~9.5.0
npm install --save-dev @tsconfig/react-native@^3.0.6
npm install --save-dev typescript@^5.1.3
npm install --save-dev babel-plugin-macros@^3.1.0

原生项目生成阶段

1
2
3
4
5
6
# 6. 生成原生项目
npx expo prebuild

# 7. 清理缓存重新生成(多次执行以解决问题)
npx expo prebuild --clean
npx expo start --clear

问题解决阶段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 8. 解决依赖问题
npm install babel-plugin-macros --save-dev
npm install @tsconfig/react-native --save-dev

# 9. 重新安装所有依赖
rm -rf node_modules
npm install

# 10. 测试不同平台
npx expo start           # 开发服务器
npx expo run:android     # Android 测试
npx expo start --web     # Web 测试

配置调整阶段

1
2
3
4
5
# 11. 环境变量设置(Android SDK)
setx ANDROID_HOME "D:\Android\Sdk"

# 12. 验证环境
echo %ANDROID_HOME%

迁移脚本内容

migrate-code.bat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@echo off
chcp 65001 > nul
echo 开始迁移代码...

echo 正在复制应用代码...
robocopy "..\App\app" "app" /E /XD node_modules .git android ios

echo 正在复制依赖库...
robocopy "..\App\deps" "deps" /E /XD node_modules .git

echo 正在复制原生模块...
if exist "android\app\src\main\java" (
    robocopy "..\App\android\app\src\main\java" "android\app\src\main\java" /E
)

echo 正在复制 iOS 原生代码...
if exist "ios" (
    robocopy "..\App\ios" "ios" *.h *.m *.mm *.swift /S
)

echo 正在复制补丁文件...
robocopy "..\App\patches" "patches" /E

echo 代码迁移完成!
pause

🛠️ 解决策略总结

1. 渐进式迁移策略

第一阶段:最小化可行产品

  • 只保留核心 Expo 依赖
  • 移除所有非必要插件
  • 使用简化的 App 组件

第二阶段:逐步添加功能

  • 一次添加一个模块
  • 每次添加后测试应用启动
  • 记录哪些模块会导致问题

第三阶段:原生模块集成

  • 在基本功能稳定后添加 RFID 等原生模块
  • 使用 Expo Config Plugins 处理原生配置

2. 调试最佳实践

缓存管理:

1
2
3
4
5
# 清理所有缓存
npx expo start --clear
rm -rf node_modules
npm install
npx expo prebuild --clean

日志分析:

  • 关注 Metro bundler 输出
  • 检查 Android Logcat 中的详细错误
  • 使用 expo doctor 诊断配置问题

配置验证:

  • 确保 package.json 中的 main 字段正确
  • 检查 app.json 配置语法
  • 验证 babel.config.js 插件都已安装

3. 依赖管理策略

核心原则:

  1. 最小依赖原则: 只安装必需的包
  2. 版本兼容性: 使用 Expo SDK 推荐的版本
  3. 渐进添加: 一次添加一个依赖并测试

推荐的最小依赖集:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "dependencies": {
    "expo": "~50.0.0",
    "expo-status-bar": "~1.11.0",
    "react": "18.2.0",
    "react-native": "0.72.10"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "babel-preset-expo": "~9.5.0"
  }
}

迁移过程中创建的文件清单

新项目结构 (InventoryExpo/)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
InventoryExpo/
├── 📱 核心配置文件
│   ├── app.json              # Expo 项目配置
│   ├── eas.json              # EAS 构建配置
│   ├── metro.config.js       # Metro 打包配置
│   ├── babel.config.js       # Babel 转换配置
│   ├── tsconfig.json         # TypeScript 配置
│   └── package.json          # 依赖管理
├── 📋 入口文件
│   ├── index.js              # Expo 应用入口
│   └── App.js                # 应用主组件(简化版)
├── 🖼️ 资源文件
│   └── assets/
│       ├── icon.png          # 应用图标
│       ├── adaptive-icon.png # Android 自适应图标
│       ├── splash.png        # 启动画面
│       └── favicon.png       # Web 图标
├── 📱 原生项目(自动生成)
│   ├── android/              # Android 项目
│   └── ios/                  # iOS 项目
├── 📚 迁移代码
│   ├── app/                  # 从原项目复制的应用代码
│   ├── deps/                 # 依赖库
│   └── patches/              # 补丁文件
└── 📖 文档文件
    ├── MIGRATION_SUCCESS.md     # 迁移成功总结
    ├── DEPENDENCY_MIGRATION.md  # 依赖迁移指南
    ├── MIGRATION_COMPLETION.md  # 完成状态
    └── NEXT_STEPS.md           # 下一步计划

迁移工具文件

1
2
3
4
Inventory/ (根目录)
├── migrate-code.bat                    # 代码迁移批处理脚本
├── EXPO_MIGRATION_TROUBLESHOOTING.md  # 本故障排除文档
└── InventoryExpo/                      # 新的 Expo 项目

配置文件对比

package.json 变化

原始项目依赖:

1
2
3
4
5
6
{
  "react-native": "0.71.10",
  "react-native-quick-sqlite": "^8.0.0-beta.2",
  "react-native-fs": "^2.20.0",
  "react-native-vision-camera": "^2.15.4"
}

迁移后依赖:

1
2
3
4
5
6
7
{
  "expo": "~50.0.0",
  "react-native": "0.72.10",
  "expo-sqlite": "~13.0.0",
  "expo-file-system": "~16.0.0",
  "expo-camera": "~14.0.0"
}

构建脚本变化

原始项目:

1
2
3
4
5
6
7
{
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start"
  }
}

迁移后:

1
2
3
4
5
6
7
{
  "scripts": {
    "android": "expo run:android",
    "ios": "expo run:ios", 
    "start": "expo start --dev-client"
  }
}

📊 问题频率统计

问题类型 发生次数 解决难度 影响程度
依赖缺失 3次
权限错误 2次
应用注册失败 2次
配置错误 1次

🎯 关键学习要点

1. Expo Bare Workflow 特点

  • 保留原生代码: 可以使用自定义原生模块
  • Expo 工具链: 享受 Expo 的开发和构建工具
  • 配置复杂性: 需要同时管理 Expo 和原生配置

2. 迁移过程中的注意事项

  • 分阶段进行: 不要一次性迁移所有代码
  • 权限管理: Android 权限问题可能很复杂
  • 依赖版本: 严格按照 Expo SDK 版本要求
  • 缓存清理: 经常清理各种缓存

3. 调试技巧

  • 错误信息分析: 仔细阅读完整的错误堆栈
  • 隔离问题: 通过移除代码定位问题源头
  • 文档查阅: 查阅 Expo 官方文档和 GitHub Issues

4. 最佳实践

  • 版本控制: 每个工作阶段都要提交代码
  • 文档记录: 记录所有问题和解决方案
  • 测试驱动: 每次更改后都要测试基本功能

🔄 当前状态和下一步

当前问题状态

  • ✅ babel-plugin-macros 安装完成
  • ✅ TypeScript 配置修复
  • ✅ app.json 权限简化
  • ❌ Android 权限拒绝错误(仍存在)
  • ❌ 应用注册失败(仍存在)

下一步计划

  1. 进一步简化依赖: 移除可能有问题的 Expo 模块
  2. 创建最小化测试应用: 从头开始验证基本功能
  3. 逐步添加原始功能: 确认每个模块的兼容性
  4. 原生模块集成: 在基本功能稳定后添加 RFID 模块

备选方案

如果当前方法无法解决:

  1. 重新创建项目: 使用 expo init 创建新项目后迁移代码
  2. 降级 Expo SDK: 尝试使用较旧但更稳定的版本
  3. 混合方案: 保留部分 React Native CLI 结构

📚 参考资源

官方文档

社区资源

调试工具

  • expo doctor - 配置诊断
  • npx react-native info - 环境信息
  • Android Studio Logcat - Android 日志

文档创建时间: 2025年7月23日
最后更新时间: 2025年7月23日
文档状态: 进行中

💡 提示: 这是一个活跃文档,会随着问题解决和新发现持续更新。建议在每次遇到新问题或找到解决方案时都更新此文档。