中文资讯 掘金 AI Thu, 08 Oct 2026 正文 ok 2312 words

移动端原生框架对比评测

英文标题:移动端原生框架对比评测

移动端开发技术知识库 一、技术分类总览 按渲染方式和技术架构,分为四大阵营: 阵营 代表技术 渲染方式 性能 自绘引擎 Flutter 自带渲染引擎,直接绘制像素 ⭐⭐⭐⭐⭐ 原生组件映射 React
打开原文相关 3 · 机会 0
media3.2 KB media589 B media8.6 KB

中文

移动端开发技术知识库

一、技术分类总览

按渲染方式和技术架构,分为四大阵营:

阵营 代表技术 渲染方式 性能
自绘引擎 Flutter 自带渲染引擎,直接绘制像素 ⭐⭐⭐⭐⭐
原生组件映射 React Native 映射到原生组件 ⭐⭐⭐⭐
WebView + 原生桥接 Ionic / Cordova / PhoneGap WebView 渲染 HTML/CSS/JS ⭐⭐
WebView 套壳 H5 套壳 纯 WebView,无桥接 ⭐

二、各技术详解

2.1 Flutter(自绘引擎)

  • 原理 :自带 Skia 渲染引擎,不依赖平台原生组件,直接在 Canvas 上绘制像素
  • 优点 :性能最接近原生,UI 一致性极好(各平台看起来完全一样)
  • 缺点 :包体积大(引擎约 5-10MB),Dart 语言生态相对小,无法直接使用原生组件
  • 适用 :对性能和 UI 一致性要求高的应用

2.2 React Native(原生组件映射)

  • 原理 :JS 写 UI → 通过 Bridge 转换 → 调用平台原生组件渲染
  • 优点 :使用原生组件,体验接近原生;JS 生态丰富;新架构 Fabric + TurboModules 大幅提升性能
  • 缺点 :Bridge 通信有开销;复杂动画性能不如 Flutter;需要了解原生开发知识
  • 适用 :已有 JS/React 技术栈的团队

2.3 Ionic / Taro / UniApp(跨端框架)

Ionic
  • 本质 :WebView 渲染 + Capacitor/Cordova 提供原生 API 桥接
  • 技术栈 :Angular/React/Vue + HTML/CSS/JS
  • 特点 :本质还是 WebView 渲染,但通过桥接可以调用原生 API
Taro(京东出品)
  • 本质 :一套代码编译到多端(小程序、H5、RN)
  • 技术栈 :React/Vue 语法 → 编译到各端
  • 特点 :核心优势是跨小程序端(微信/支付宝/百度等),不是追求原生性能
UniApp(DCloud 出品)
  • 本质 :类似 Taro,一套代码编译到多端
  • 技术栈 :Vue 语法 → 编译到各端
  • 特点 :生态更完善,插件市场丰富;App 端底层用 WebView + weex(部分原生渲染)

Taro 和 UniApp 的核心价值:不是"高性能 App",而是"一套代码跑小程序 + H5 + App",解决的是多端维护成本问题。

2.4 Cordova / PhoneGap(WebView + 原生桥接)

2.5 H5 套壳(纯 WebView 包装)


三、H5 套壳 vs Cordova 的区别

对比项 H5 套壳 Cordova
渲染方式 WebView WebView(一样)
渲染性能 一样慢 一样慢
原生 API 访问 ❌ 默认不能 ✅ 通过插件桥接
JS 调原生能力 无桥接机制 有 cordova.exec() Bridge
插件生态 无 丰富的插件市场
开发复杂度 极低(10行代码) 低(需配置 Cordova 项目)
本质区别 纯壳,无通信 壳 + 通信桥接

H5 套壳能使用原生 API 吗?

默认不能。纯 H5 套壳就是:

  • WebView 里的 JS 只能调用浏览器标准 API(navigator.geolocation 等)
  • 无法调用相机、推送、蓝牙、通讯录等原生能力
  • 除非自己写桥接(类似自己实现一个简化版 Cordova)

如果想在 H5 套壳里调用原生 API,有两条路:

  1. 自己写 JS Bridge:原生端注册 handler,JS 端通过 window.webkit.messageHandlers(iOS)或 WebView.addJavascriptInterface(Android)通信
  2. 直接用 Cordova:它已经帮你做好了这件事

Cordova 本质上 = H5 套壳 + 原生 API 桥接 + 插件生态


四、WebView、Bridge、桥接能力

4.1 WebView 是什么?

WebView 就是移动端操作系统内嵌的一个"浏览器内核组件"。

Chrome 浏览器 = 地址栏 + 标签页 + 书签 + 前进后退按钮 + 渲染引擎
WebView     = 只有渲染引擎(去掉浏览器外壳)

各平台的 WebView:

平台 WebView 组件 底层内核
Android android.webkit.WebView Chromium(4.4+)
iOS WKWebView WebKit(Safari 同内核)
鸿蒙 Web 组件 Chromium 内核

代码层面的理解(Android):

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />



WebView webView = findViewById(R.id.webview);
webView.loadUrl("https://www.baidu.com");
webView.loadUrl("file:///android_asset/index.html");

iOS 端:

let webView = WKWebView(frame: view.bounds)
webView.load(URLRequest(url: URL(string: "https://www.baidu.com")!))
view.addSubview(webView)

WebView 能做什么:

  • ✅ 渲染 HTML/CSS/JS(和浏览器一模一样)
  • ✅ 加载远程 URL 或本地 HTML 文件
  • ✅ 执行 JavaScript 代码
  • ❌ 默认不能调用原生 API(相机、GPS、推送等)
  • ❌ 没有浏览器地址栏、导航栏等 UI

4.2 Bridge 是什么?

Bridge(桥)是 WebView 里的 JS 和原生代码之间通信的通道。

为什么需要 Bridge:

你的 H5 页面里有一个按钮:"拍照上传"

JS 想做的事:调用手机摄像头 → 拍照 → 拿到照片 → 上传

问题:
- JS 运行在 WebView 里(浏览器环境)
- 浏览器环境没有"调用摄像头"这个原生 API
- 摄像头 API 只存在于原生代码中(Java/Kotlin/Swift)

JS 和原生代码,就像隔了一条河的两个岛,互不相通



┌─────────────────┐          ┌─────────────────┐
│   WebView 岛     │    河    │   原生岛          │
│                 │ ←无法通信→ │                 │
│  JS 代码        │          │  Java/Swift 代码  │
│  想调摄像头 ❌    │          │  有摄像头 API ✅   │
└─────────────────┘          └─────────────────┘

                    ↓ 加 Bridge ↓

┌─────────────────┐          ┌─────────────────┐
│   WebView 岛     │          │   原生岛          │
│                 │  Bridge  │                 │
│  JS 代码        │ ════════ │  Java/Swift 代码  │
│  调用摄像头 ✅    │  通信通道  │  有摄像头 API ✅   │
└─────────────────┘          └─────────────────┘

Bridge 支持双向通信:

方向1:JS → 原生(JS 调用原生能力)
  JS: "帮我打开摄像头"
  → Bridge 传递消息 →
  原生: 打开摄像头,返回照片

方向2:原生 → JS(原生通知 JS)
  原生: "收到一条推送通知"
  → Bridge 传递消息 →
  JS: 在页面上显示通知

Bridge 的底层实现:

Android 端(方式1:addJavascriptInterface):

webView.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public void openCamera() {
        
    }
}, "NativeBridge");

Android 端(方式2:prompt 拦截):

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onJsPrompt(WebView view, String url, String message,
                              String defaultValue, JsPromptResult result) {
        if (message.equals("openCamera")) {
            openCamera();
            result.confirm("success");
            return true;
        }
        return false;
    }
});

iOS 端:

let contentController = WKUserContentController()
contentController.add(self, name: "NativeBridge")



webView.evaluateJavaScript("onPhotoReceived('photo_base64')")

Bridge 通信的数据格式(通常使用 JSON):

{
  "method": "openCamera",
  "params": { "quality": "high", "maxSize": 1024 },
  "callbackId": "cb_001"
}



{
  "callbackId": "cb_001",
  "status": "success",
  "data": { "photoPath": "/path/to/photo.jpg" }
}

4.3 桥接能力是什么?

桥接能力 = 通过 Bridge 暴露给 JS 调用的原生功能的集合。

能力分类 具体功能 JS 原生能做吗 需要桥接吗
设备信息 获取设备型号、系统版本 ❌ ✅
相机 拍照、录像、扫码 ❌ ✅
地理位置 GPS 定位 部分(精度低) ✅
文件系统 读写本地文件 ❌ ✅
推送通知 发送/接收通知 ❌ ✅
蓝牙 连接蓝牙设备 ❌ ✅
通讯录 读取联系人 ❌ ✅
生物识别 指纹/面容识别 ❌ ✅

不同框架的桥接能力:

H5 套壳:     无桥接能力(除非自己写)
Cordova:     丰富的插件生态(1000+ 插件)
Ionic:       使用 Capacitor(Cordova 的现代替代)
React Native:自有 Bridge + TurboModules
Flutter:     Platform Channel(自研桥接机制)

4.4 完整调用流程示例(拍照上传)

用户点击 H5 页面的"拍照"按钮
        │
        ▼
JS 调用:window.NativeBridge.call('openCamera', {quality: 'high'})
        │
        ▼ Bridge 传递
        │
原生端收到消息:解析 method = "openCamera"
        │
        ▼
原生调用系统 API:Camera.open() → 拍照 → 获取照片
        │
        ▼ Bridge 回传
        │
JS 收到回调:callback({photoPath: "/path/to/photo.jpg"})
        │
        ▼
JS 将照片显示在页面上 / 上传到服务器

三者关系:WebView(载体)+ Bridge(通道)+ 桥接能力(功能)= 混合开发 App


五、Swift 原生 vs Flutter vs React Native

5.1 本质区别

Swift 原生开发:  代码 → 直接编译为机器码 → 运行在 iOS 设备上
Flutter:        Dart 代码 → 编译为 ARM 机器码 → 自绘引擎渲染 UI
React Native:   JS 代码 → Bridge → 调用 iOS 原生组件渲染
维度 Swift 原生 Flutter React Native
语言 Swift Dart JavaScript
UI 渲染 iOS 原生组件 自绘引擎(Skia) 映射到原生组件
编译产物 原生机器码 原生机器码 JS Bundle + 原生壳
平台支持 仅 iOS/macOS iOS + Android + Web + 桌面 iOS + Android
运行性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐½ ⭐⭐⭐⭐

5.2 UI 渲染机制的区别

Swift 原生 —— 直接使用系统组件

Swift 代码 → 直接调用 iOS UIKit/SwiftUI 组件 → 系统渲染(UILabel, UIView 等)
  • 用的是 Apple 自己的组件,外观、动画、交互 100% 符合 iOS 规范
  • 系统更新组件样式,App 自动跟着变

Flutter —— 自己画一切

Dart 代码 → Flutter Framework(Widget 树)→ Skia 渲染引擎 → 直接在 Canvas 上画像素
  • 完全不使用 iOS 原生组件,Flutter 自己用 Skia 画了一个"Text"、一个"Button"
  • iOS 和 Android 上看起来一模一样(都是画出来的)
  • 代价:和系统原生风格有细微差异,系统更新 UI 风格时 Flutter 不会自动跟随

React Native —— 映射到原生组件

JSX 代码 → React Native 解析 → Bridge 传递指令 → iOS 端创建真正的 UIView/UILabel → 系统渲染
  • <Text> 在 iOS 上真的创建了一个 UILabel
  • 渲染出来的是真正的 iOS 原生组件,外观和原生一致
  • 代价:JS 和原生之间 Bridge 通信有延迟

5.3 性能对比

场景 Swift Flutter RN
简单页面 极快 极快 快
复杂列表 极快 很快 较快(需优化)
复杂动画 极快 很快 一般
频繁交互 极快 很快 Bridge 可能卡顿

RN 的性能瓶颈(旧架构):

JS 线程                    Bridge(序列化/反序列化)           原生线程
┌──────────┐              ┌──────────────┐              ┌──────────┐
│ JS 逻辑    │ ──JSON消息──→ │   Bridge     │ ──解析消息──→ │ 原生组件  │
│ 虚拟 DOM   │ ←─JSON消息── │  (异步队列)   │ ←─回传结果── │ 渲染执行  │
└──────────┘              └──────────────┘              └──────────┘

问题:每次交互都要跨 Bridge → 序列化 → 反序列化 → 异步等待

RN 新架构(Fabric + TurboModules):

JS 线程                     JSI(直接引用)              原生线程
┌──────────┐              ┌──────────────┐              ┌──────────┐
│ JS 逻辑    │ ──C++直接调用─→ │    JSI       │ ──同步调用──→ │ 原生组件  │
│ 虚拟 DOM   │ ←──直接返回─── │ (同步桥接)    │ ←─直接返回─── │ 渲染执行  │
└──────────┘              └──────────────┘              └──────────┘

改进:JSI 允许 JS 直接持有 C++ 对象引用,无需序列化

5.4 开发体验对比

| Swift| Dart/Flutter| JavaScript/RN
---|---|---|---
学习曲线| 中等| 低(类似 JS + Java)| 低(前端开发者熟悉)
类型系统| 强类型,优秀| 强类型,优秀| 弱类型(TS 可弥补)
生态规模| Apple 生态,丰富| Flutter 生态,够用| npm 最大生态
热重载| ❌ 需重新编译| ✅ 秒级热重载| ✅ 秒级热重载

5.5 平台能力访问

Swift:    100
Flutter:  90
RN:       90

常用能力(相机、定位、推送)→ 三个方案都能轻松搞定
冷门能力(ARKit、HealthKit、HomeKit)→ Swift 直接用,Flutter/RN 要自己写桥接
新出的 iOS API → Swift 立刻能用,Flutter/RN 要等插件或自己实现

5.6 App 体积对比

Swift 原生 App:    ~2-5 MB(空项目)
Flutter App:       ~15-20 MB(含 Skia 引擎 + Dart 运行时)
React Native App:  ~8-12 MB(含 JSC/Hermes 引擎 + JS Bundle)

5.7 选型建议

选 Swift 原生:
  ✅ 只做 iOS 平台,不需要 Android
  ✅ 深度依赖 iOS 专有功能(ARKit、HealthKit、SiriKit 等)
  ✅ 对性能要求极致(游戏、视频编辑、实时音频处理)
  ✅ 追求最完美的 iOS 体验和系统一致性

选 Flutter:
  ✅ 需要 iOS + Android 双端,且追求高性能
  ✅ UI 复杂、动画多、自定义程度高
  ✅ 未来可能扩展到 Web / 桌面
  ✅ 对 UI 一致性要求高(双端看起来一样)

选 React Native:
  ✅ 需要 iOS + Android 双端
  ✅ 团队已有 React/JS 技术栈
  ✅ 内容展示类 App(电商、社交、资讯)
  ✅ 希望复用 Web 端的 JS 逻辑/状态管理
  ✅ 需要热更新(App Store 不用重新审核)

六、最小启动步骤

6.1 Swift(iOS 原生)

mkdir MySwiftApp && cd MySwiftApp

open -a Xcode .

最小 SwiftUI 代码:

import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Text("Hello, iOS!")
        }
    }
}

6.1b Kotlin(Android 原生)

最小 Kotlin 代码(MainActivity.kt):

package com.example.myapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello, Android!")
        }
    }
}

Gradle 依赖(build.gradle.kts):

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.activity:activity-compose:1.8.0")
    implementation(platform("androidx.compose:compose-bom:2024.02.00"))
    implementation("androidx.compose.material3:material3")
}

6.2 Flutter

flutter create my_app
cd my_app


flutter run

最小 Flutter 代码(已自动生成在 lib/main.dart):

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
  home: Scaffold(body: Center(child: Text('Hello, Flutter!'))),
));

6.3 React Native

npx create-expo-app my_app
cd my_app
npx expo start


npx react-native init MyApp
cd MyApp
npx react-native run-ios

最小 RN 代码(App.tsx):

import { Text, View } from 'react-native';

export default function App() {
  return <View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
    <Text>Hello, RN!</Text>
  </View>;
}

6.4 Ionic

npm install -g @ionic/cli


ionic start myApp tabs --type=vue
cd myApp


ionic serve


ionic cap add ios
ionic cap run ios

6.5 UniApp

npx degit dcloudio/uni-preset-vue
cd myApp
npm install
npm run dev:h5           
npm run dev:mp-weixin    

6.6 Taro

npx @tarojs/cli init myApp
cd myApp
npm install


npm run dev:h5           
npm run dev:weapp        
npm run dev:rn           

6.7 Cordova

npm install -g cordova


cordova create myApp com.example.myapp MyApp
cd myApp


cordova platform add ios
cordova platform add android


cordova run ios
cordova run android

6.8 H5 套壳(最小实现)

iOS 端(SwiftUI) :

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.load(URLRequest(url: URL(string: "https://your-h5-site.com")!))
        return webView
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {}
}

@main
struct ShellApp: App {
    var body: some Scene {
        WindowGroup { WebView() }
    }
}

Android 端(Kotlin) :

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val webView = WebView(this)
        webView.settings.javaScriptEnabled = true
        webView.loadUrl("https://your-h5-site.com")
        setContentView(webView)
    }
}

七、快速选型速查

追求性能 → Flutter > React Native > Ionic/Cordova > H5套壳
追求跨端(含小程序)→ UniApp / Taro
追求开发速度(已有H5)→ H5套壳(但功能受限)
需要原生API + 已有H5 → Ionic / Cordova
团队已有React → React Native
团队已有Vue → UniApp
只做 iOS → Swift
只做 Android → Kotlin

八、打包与发布

8.1 各技术打包产物概览

技术 iOS 产物 Android 产物 打包工具
Swift 原生 .ipa — Xcode
Kotlin 原生 — .apk / .aab Android Studio / Gradle
Flutter .ipa .apk / .aab flutter build
React Native .ipa .apk / .aab Xcode / Gradle / Expo
Ionic .ipa .apk / .aab ionic cap build / Xcode / Gradle
Cordova .ipa .apk / .aab cordova build / Xcode / Gradle
UniApp .ipa .apk / .aab HBuilderX 云打包 / 本地打包
Taro .ipa(RN端) .apk / .aab(RN端) 依赖 RN 打包流程
H5 套壳 .ipa .apk / .aab 取决于壳的编写方式

APK vs AAB :Google Play 自 2021 年 8 月起要求新应用必须使用 AAB(Android App Bundle)格式上传,AAB 会根据用户设备动态分发所需资源,体积更小。APK 仍可用于侧载或国内应用市场。


8.2 iOS 打包流程(所有技术通用)

前置条件
1. Apple Developer 账号($99/年,个人或公司)
2. Mac 电脑(Xcode 仅限 macOS)
3. 真机设备(用于测试,模拟器无法测试推送、相机等)
完整流程
各技术的 iOS 打包命令
flutter build ios --release



cd ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release archive


npx expo prebuild
npx expo run:ios --configuration Release

npx eas build --platform ios


cd ios && xcodebuild -workspace App.xcworkspace -scheme App -configuration Release archive


cordova build ios --release --device

8.3 Android 打包流程(所有技术通用)

前置条件
1. Android Studio
2. JDK 17+
3. 签名密钥(Release 版本必须)
完整流程
keytool -genkey -v \
  -keystore my-release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias my-alias

Gradle 签名配置(android/app/build.gradle 或 android/build.gradle):

android {
    signingConfigs {
        release {
            storeFile file("my-release-key.jks")
            storePassword "your-store-password"
            keyAlias "my-alias"
            keyPassword "your-key-password"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true      // 代码混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

生产环境不要把密码写死在代码里,使用环境变量或 local.properties:

# local.properties(不提交到 Git)
STORE_FILE=my-release-key.jks
STORE_PASSWORD=your-password
KEY_ALIAS=my-alias
KEY_PASSWORD=your-password



// build.gradle 中读取
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

signingConfigs {
    release {
        storeFile file(properties.getProperty('STORE_FILE'))
        storePassword properties.getProperty('STORE_PASSWORD')
        keyAlias properties.getProperty('KEY_ALIAS')
        keyPassword properties.getProperty('KEY_PASSWORD')
    }
}





./gradlew assembleRelease



./gradlew bundleRelease
各技术的 Android 打包命令
flutter build apk --release              
flutter build appbundle --release        


cd android && ./gradlew assembleRelease   
cd android && ./gradlew bundleRelease     


npx eas build --platform android          


cd android && ./gradlew assembleRelease


cordova build android --release

8.4 小程序打包(UniApp / Taro)

npm run build:mp-weixin    



npm run build:weapp        

8.5 签名与证书管理

平台 证书类型 有效期 丢失后果
iOS Distribution Certificate 1 年 需重新生成,不影响已上架 App
iOS Provisioning Profile 1 年 需重新生成,不影响已上架 App
Android Keystore (.jks) 25 年+ 永久丢失无法更新 App

Android 的 Keystore 一旦丢失,永远无法用相同包名发布更新 ,Google Play 和国内市场都要求相同的签名。务必备份到安全位置。


九、热更新方案

9.1 什么是热更新?

热更新 = 不经过应用商店审核,直接下发代码/资源更新到用户设备。

传统更新:发现 Bug → 修复 → 打包 → 提交审核 → 等待 1-3 天 → 用户下载更新
热更新:   发现 Bug → 修复 → 上传补丁 → 秒级生效 → 用户下次打开自动更新

9.2 各技术支持情况

技术 热更新支持 方案 限制
Swift 原生 ❌ 不支持 — Apple 禁止热更新原生代码
Kotlin 原生 ❌ 不支持 — Google 限制较少,但原生代码热更新也不推荐
Flutter ⚠️ 有限支持 shorebird、flutter_code_push 社区方案,非官方
React Native ✅ 支持 CodePush、Expo Updates JS Bundle 可热更新,原生模块不行
Ionic / Cordova ✅ 支持 CodePush、自定义实现 Web 资源可热更新
UniApp ✅ 支持 DCloud 云打包热更新 官方支持,WGT 资源包更新
Taro ⚠️ 有限支持 依赖 RN 端的热更新能力 H5/小程序端天然支持(就是网页)

9.3 React Native 热更新(CodePush)

npm install -g appcenter-cli


appcenter login


appcenter codepush release-react -a MyOrg/MyApp -d Production



import codePush from 'react-native-code-push';

function App() {
  
}

export default codePush({
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME
})(App);

9.4 UniApp 热更新

uni.request({
  url: 'https://your-server.com/check-update',
  success: (res) => {
    if (res.data.hasUpdate) {
      uni.downloadFile({
        url: res.data.wgtUrl,
        success: (downloadRes) => {
          uni.installUpdate({
            filePath: downloadRes.tempFilePath
          });
        }
      });
    }
  }
});

9.5 Apple 对热更新的限制

Apple App Store 审核指南 2.5.2:
"App 不得下载或安装可执行代码"

允许:
  ✅ JS 脚本解释执行(RN、WebView 内的 JS)
  ✅ 资源文件更新(图片、配置)
  ✅ 使用 Apple 的 JavaScriptCore 框架

禁止:
  ❌ 下载并执行原生机器码
  ❌ 使用 dlopen、dlsym 等动态加载
  ❌ 绕过审核机制更新核心功能

十、调试方式

10.1 各技术调试工具

技术 调试工具 断点调试 UI 检查 性能分析
Swift Xcode ✅ LLDB ✅ View Debugger ✅ Instruments
Kotlin Android Studio ✅ ✅ Layout Inspector ✅ Profiler
Flutter Flutter DevTools ✅ ✅ Widget Inspector ✅ Performance
React Native Chrome DevTools / Flipper ✅ ✅ Element Inspector ✅ Hermes Profiler
Ionic Chrome DevTools ✅ ✅ ❌(依赖浏览器工具)
UniApp HBuilderX / 微信开发者工具 ❌ ✅ ❌
Taro 微信开发者工具 / Chrome ❌ ✅ ❌

10.2 真机调试

10.3 日志查看

idevicesyslog | grep MyApp


adb logcat -s "MyApp:D"    
adb logcat | grep flutter   
adb logcat | grep ReactNativeJS  

十一、鸿蒙 HarmonyOS(补充)

11.1 鸿蒙开发技术

技术 说明 适用场景
ArkTS(原生) 鸿蒙官方语言,TypeScript 超集 追求最佳性能和体验
ArkUI(声明式 UI) 类似 SwiftUI / Flutter 的声明式语法 鸿蒙原生 App
元服务(Atomic Service) 免安装、卡片化 轻量服务
跨平台框架适配 Flutter、RN 已有鸿蒙适配版本 已有跨平台项目迁移

11.2 最小启动步骤(ArkTS)

最小 ArkTS 代码(Index.ets):

@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Hello, HarmonyOS!')
        .fontSize(24)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

11.3 鸿蒙打包

English / 原文

移动端开发技术知识库

一、技术分类总览

按渲染方式和技术架构,分为四大阵营:

阵营 代表技术 渲染方式 性能
自绘引擎 Flutter 自带渲染引擎,直接绘制像素 ⭐⭐⭐⭐⭐
原生组件映射 React Native 映射到原生组件 ⭐⭐⭐⭐
WebView + 原生桥接 Ionic / Cordova / PhoneGap WebView 渲染 HTML/CSS/JS ⭐⭐
WebView 套壳 H5 套壳 纯 WebView,无桥接 ⭐

二、各技术详解

2.1 Flutter(自绘引擎)

  • 原理 :自带 Skia 渲染引擎,不依赖平台原生组件,直接在 Canvas 上绘制像素
  • 优点 :性能最接近原生,UI 一致性极好(各平台看起来完全一样)
  • 缺点 :包体积大(引擎约 5-10MB),Dart 语言生态相对小,无法直接使用原生组件
  • 适用 :对性能和 UI 一致性要求高的应用

2.2 React Native(原生组件映射)

  • 原理 :JS 写 UI → 通过 Bridge 转换 → 调用平台原生组件渲染
  • 优点 :使用原生组件,体验接近原生;JS 生态丰富;新架构 Fabric + TurboModules 大幅提升性能
  • 缺点 :Bridge 通信有开销;复杂动画性能不如 Flutter;需要了解原生开发知识
  • 适用 :已有 JS/React 技术栈的团队

2.3 Ionic / Taro / UniApp(跨端框架)

Ionic
  • 本质 :WebView 渲染 + Capacitor/Cordova 提供原生 API 桥接
  • 技术栈 :Angular/React/Vue + HTML/CSS/JS
  • 特点 :本质还是 WebView 渲染,但通过桥接可以调用原生 API
Taro(京东出品)
  • 本质 :一套代码编译到多端(小程序、H5、RN)
  • 技术栈 :React/Vue 语法 → 编译到各端
  • 特点 :核心优势是跨小程序端(微信/支付宝/百度等),不是追求原生性能
UniApp(DCloud 出品)
  • 本质 :类似 Taro,一套代码编译到多端
  • 技术栈 :Vue 语法 → 编译到各端
  • 特点 :生态更完善,插件市场丰富;App 端底层用 WebView + weex(部分原生渲染)

Taro 和 UniApp 的核心价值:不是"高性能 App",而是"一套代码跑小程序 + H5 + App",解决的是多端维护成本问题。

2.4 Cordova / PhoneGap(WebView + 原生桥接)

2.5 H5 套壳(纯 WebView 包装)


三、H5 套壳 vs Cordova 的区别

对比项 H5 套壳 Cordova
渲染方式 WebView WebView(一样)
渲染性能 一样慢 一样慢
原生 API 访问 ❌ 默认不能 ✅ 通过插件桥接
JS 调原生能力 无桥接机制 有 cordova.exec() Bridge
插件生态 无 丰富的插件市场
开发复杂度 极低(10行代码) 低(需配置 Cordova 项目)
本质区别 纯壳,无通信 壳 + 通信桥接

H5 套壳能使用原生 API 吗?

默认不能。纯 H5 套壳就是:

  • WebView 里的 JS 只能调用浏览器标准 API(navigator.geolocation 等)
  • 无法调用相机、推送、蓝牙、通讯录等原生能力
  • 除非自己写桥接(类似自己实现一个简化版 Cordova)

如果想在 H5 套壳里调用原生 API,有两条路:

  1. 自己写 JS Bridge:原生端注册 handler,JS 端通过 window.webkit.messageHandlers(iOS)或 WebView.addJavascriptInterface(Android)通信
  2. 直接用 Cordova:它已经帮你做好了这件事

Cordova 本质上 = H5 套壳 + 原生 API 桥接 + 插件生态


四、WebView、Bridge、桥接能力

4.1 WebView 是什么?

WebView 就是移动端操作系统内嵌的一个"浏览器内核组件"。

Chrome 浏览器 = 地址栏 + 标签页 + 书签 + 前进后退按钮 + 渲染引擎
WebView     = 只有渲染引擎(去掉浏览器外壳)

各平台的 WebView:

平台 WebView 组件 底层内核
Android android.webkit.WebView Chromium(4.4+)
iOS WKWebView WebKit(Safari 同内核)
鸿蒙 Web 组件 Chromium 内核

代码层面的理解(Android):

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />



WebView webView = findViewById(R.id.webview);
webView.loadUrl("https://www.baidu.com");
webView.loadUrl("file:///android_asset/index.html");

iOS 端:

let webView = WKWebView(frame: view.bounds)
webView.load(URLRequest(url: URL(string: "https://www.baidu.com")!))
view.addSubview(webView)

WebView 能做什么:

  • ✅ 渲染 HTML/CSS/JS(和浏览器一模一样)
  • ✅ 加载远程 URL 或本地 HTML 文件
  • ✅ 执行 JavaScript 代码
  • ❌ 默认不能调用原生 API(相机、GPS、推送等)
  • ❌ 没有浏览器地址栏、导航栏等 UI

4.2 Bridge 是什么?

Bridge(桥)是 WebView 里的 JS 和原生代码之间通信的通道。

为什么需要 Bridge:

你的 H5 页面里有一个按钮:"拍照上传"

JS 想做的事:调用手机摄像头 → 拍照 → 拿到照片 → 上传

问题:
- JS 运行在 WebView 里(浏览器环境)
- 浏览器环境没有"调用摄像头"这个原生 API
- 摄像头 API 只存在于原生代码中(Java/Kotlin/Swift)

JS 和原生代码,就像隔了一条河的两个岛,互不相通



┌─────────────────┐          ┌─────────────────┐
│   WebView 岛     │    河    │   原生岛          │
│                 │ ←无法通信→ │                 │
│  JS 代码        │          │  Java/Swift 代码  │
│  想调摄像头 ❌    │          │  有摄像头 API ✅   │
└─────────────────┘          └─────────────────┘

                    ↓ 加 Bridge ↓

┌─────────────────┐          ┌─────────────────┐
│   WebView 岛     │          │   原生岛          │
│                 │  Bridge  │                 │
│  JS 代码        │ ════════ │  Java/Swift 代码  │
│  调用摄像头 ✅    │  通信通道  │  有摄像头 API ✅   │
└─────────────────┘          └─────────────────┘

Bridge 支持双向通信:

方向1:JS → 原生(JS 调用原生能力)
  JS: "帮我打开摄像头"
  → Bridge 传递消息 →
  原生: 打开摄像头,返回照片

方向2:原生 → JS(原生通知 JS)
  原生: "收到一条推送通知"
  → Bridge 传递消息 →
  JS: 在页面上显示通知

Bridge 的底层实现:

Android 端(方式1:addJavascriptInterface):

webView.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public void openCamera() {
        
    }
}, "NativeBridge");

Android 端(方式2:prompt 拦截):

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onJsPrompt(WebView view, String url, String message,
                              String defaultValue, JsPromptResult result) {
        if (message.equals("openCamera")) {
            openCamera();
            result.confirm("success");
            return true;
        }
        return false;
    }
});

iOS 端:

let contentController = WKUserContentController()
contentController.add(self, name: "NativeBridge")



webView.evaluateJavaScript("onPhotoReceived('photo_base64')")

Bridge 通信的数据格式(通常使用 JSON):

{
  "method": "openCamera",
  "params": { "quality": "high", "maxSize": 1024 },
  "callbackId": "cb_001"
}



{
  "callbackId": "cb_001",
  "status": "success",
  "data": { "photoPath": "/path/to/photo.jpg" }
}

4.3 桥接能力是什么?

桥接能力 = 通过 Bridge 暴露给 JS 调用的原生功能的集合。

能力分类 具体功能 JS 原生能做吗 需要桥接吗
设备信息 获取设备型号、系统版本 ❌ ✅
相机 拍照、录像、扫码 ❌ ✅
地理位置 GPS 定位 部分(精度低) ✅
文件系统 读写本地文件 ❌ ✅
推送通知 发送/接收通知 ❌ ✅
蓝牙 连接蓝牙设备 ❌ ✅
通讯录 读取联系人 ❌ ✅
生物识别 指纹/面容识别 ❌ ✅

不同框架的桥接能力:

H5 套壳:     无桥接能力(除非自己写)
Cordova:     丰富的插件生态(1000+ 插件)
Ionic:       使用 Capacitor(Cordova 的现代替代)
React Native:自有 Bridge + TurboModules
Flutter:     Platform Channel(自研桥接机制)

4.4 完整调用流程示例(拍照上传)

用户点击 H5 页面的"拍照"按钮
        │
        ▼
JS 调用:window.NativeBridge.call('openCamera', {quality: 'high'})
        │
        ▼ Bridge 传递
        │
原生端收到消息:解析 method = "openCamera"
        │
        ▼
原生调用系统 API:Camera.open() → 拍照 → 获取照片
        │
        ▼ Bridge 回传
        │
JS 收到回调:callback({photoPath: "/path/to/photo.jpg"})
        │
        ▼
JS 将照片显示在页面上 / 上传到服务器

三者关系:WebView(载体)+ Bridge(通道)+ 桥接能力(功能)= 混合开发 App


五、Swift 原生 vs Flutter vs React Native

5.1 本质区别

Swift 原生开发:  代码 → 直接编译为机器码 → 运行在 iOS 设备上
Flutter:        Dart 代码 → 编译为 ARM 机器码 → 自绘引擎渲染 UI
React Native:   JS 代码 → Bridge → 调用 iOS 原生组件渲染
维度 Swift 原生 Flutter React Native
语言 Swift Dart JavaScript
UI 渲染 iOS 原生组件 自绘引擎(Skia) 映射到原生组件
编译产物 原生机器码 原生机器码 JS Bundle + 原生壳
平台支持 仅 iOS/macOS iOS + Android + Web + 桌面 iOS + Android
运行性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐½ ⭐⭐⭐⭐

5.2 UI 渲染机制的区别

Swift 原生 —— 直接使用系统组件

Swift 代码 → 直接调用 iOS UIKit/SwiftUI 组件 → 系统渲染(UILabel, UIView 等)
  • 用的是 Apple 自己的组件,外观、动画、交互 100% 符合 iOS 规范
  • 系统更新组件样式,App 自动跟着变

Flutter —— 自己画一切

Dart 代码 → Flutter Framework(Widget 树)→ Skia 渲染引擎 → 直接在 Canvas 上画像素
  • 完全不使用 iOS 原生组件,Flutter 自己用 Skia 画了一个"Text"、一个"Button"
  • iOS 和 Android 上看起来一模一样(都是画出来的)
  • 代价:和系统原生风格有细微差异,系统更新 UI 风格时 Flutter 不会自动跟随

React Native —— 映射到原生组件

JSX 代码 → React Native 解析 → Bridge 传递指令 → iOS 端创建真正的 UIView/UILabel → 系统渲染
  • <Text> 在 iOS 上真的创建了一个 UILabel
  • 渲染出来的是真正的 iOS 原生组件,外观和原生一致
  • 代价:JS 和原生之间 Bridge 通信有延迟

5.3 性能对比

场景 Swift Flutter RN
简单页面 极快 极快 快
复杂列表 极快 很快 较快(需优化)
复杂动画 极快 很快 一般
频繁交互 极快 很快 Bridge 可能卡顿

RN 的性能瓶颈(旧架构):

JS 线程                    Bridge(序列化/反序列化)           原生线程
┌──────────┐              ┌──────────────┐              ┌──────────┐
│ JS 逻辑    │ ──JSON消息──→ │   Bridge     │ ──解析消息──→ │ 原生组件  │
│ 虚拟 DOM   │ ←─JSON消息── │  (异步队列)   │ ←─回传结果── │ 渲染执行  │
└──────────┘              └──────────────┘              └──────────┘

问题:每次交互都要跨 Bridge → 序列化 → 反序列化 → 异步等待

RN 新架构(Fabric + TurboModules):

JS 线程                     JSI(直接引用)              原生线程
┌──────────┐              ┌──────────────┐              ┌──────────┐
│ JS 逻辑    │ ──C++直接调用─→ │    JSI       │ ──同步调用──→ │ 原生组件  │
│ 虚拟 DOM   │ ←──直接返回─── │ (同步桥接)    │ ←─直接返回─── │ 渲染执行  │
└──────────┘              └──────────────┘              └──────────┘

改进:JSI 允许 JS 直接持有 C++ 对象引用,无需序列化

5.4 开发体验对比

| Swift| Dart/Flutter| JavaScript/RN
---|---|---|---
学习曲线| 中等| 低(类似 JS + Java)| 低(前端开发者熟悉)
类型系统| 强类型,优秀| 强类型,优秀| 弱类型(TS 可弥补)
生态规模| Apple 生态,丰富| Flutter 生态,够用| npm 最大生态
热重载| ❌ 需重新编译| ✅ 秒级热重载| ✅ 秒级热重载

5.5 平台能力访问

Swift:    100
Flutter:  90
RN:       90

常用能力(相机、定位、推送)→ 三个方案都能轻松搞定
冷门能力(ARKit、HealthKit、HomeKit)→ Swift 直接用,Flutter/RN 要自己写桥接
新出的 iOS API → Swift 立刻能用,Flutter/RN 要等插件或自己实现

5.6 App 体积对比

Swift 原生 App:    ~2-5 MB(空项目)
Flutter App:       ~15-20 MB(含 Skia 引擎 + Dart 运行时)
React Native App:  ~8-12 MB(含 JSC/Hermes 引擎 + JS Bundle)

5.7 选型建议

选 Swift 原生:
  ✅ 只做 iOS 平台,不需要 Android
  ✅ 深度依赖 iOS 专有功能(ARKit、HealthKit、SiriKit 等)
  ✅ 对性能要求极致(游戏、视频编辑、实时音频处理)
  ✅ 追求最完美的 iOS 体验和系统一致性

选 Flutter:
  ✅ 需要 iOS + Android 双端,且追求高性能
  ✅ UI 复杂、动画多、自定义程度高
  ✅ 未来可能扩展到 Web / 桌面
  ✅ 对 UI 一致性要求高(双端看起来一样)

选 React Native:
  ✅ 需要 iOS + Android 双端
  ✅ 团队已有 React/JS 技术栈
  ✅ 内容展示类 App(电商、社交、资讯)
  ✅ 希望复用 Web 端的 JS 逻辑/状态管理
  ✅ 需要热更新(App Store 不用重新审核)

六、最小启动步骤

6.1 Swift(iOS 原生)

mkdir MySwiftApp && cd MySwiftApp

open -a Xcode .

最小 SwiftUI 代码:

import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Text("Hello, iOS!")
        }
    }
}

6.1b Kotlin(Android 原生)

最小 Kotlin 代码(MainActivity.kt):

package com.example.myapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello, Android!")
        }
    }
}

Gradle 依赖(build.gradle.kts):

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.activity:activity-compose:1.8.0")
    implementation(platform("androidx.compose:compose-bom:2024.02.00"))
    implementation("androidx.compose.material3:material3")
}

6.2 Flutter

flutter create my_app
cd my_app


flutter run

最小 Flutter 代码(已自动生成在 lib/main.dart):

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
  home: Scaffold(body: Center(child: Text('Hello, Flutter!'))),
));

6.3 React Native

npx create-expo-app my_app
cd my_app
npx expo start


npx react-native init MyApp
cd MyApp
npx react-native run-ios

最小 RN 代码(App.tsx):

import { Text, View } from 'react-native';

export default function App() {
  return <View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
    <Text>Hello, RN!</Text>
  </View>;
}

6.4 Ionic

npm install -g @ionic/cli


ionic start myApp tabs --type=vue
cd myApp


ionic serve


ionic cap add ios
ionic cap run ios

6.5 UniApp

npx degit dcloudio/uni-preset-vue
cd myApp
npm install
npm run dev:h5           
npm run dev:mp-weixin    

6.6 Taro

npx @tarojs/cli init myApp
cd myApp
npm install


npm run dev:h5           
npm run dev:weapp        
npm run dev:rn           

6.7 Cordova

npm install -g cordova


cordova create myApp com.example.myapp MyApp
cd myApp


cordova platform add ios
cordova platform add android


cordova run ios
cordova run android

6.8 H5 套壳(最小实现)

iOS 端(SwiftUI) :

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.load(URLRequest(url: URL(string: "https://your-h5-site.com")!))
        return webView
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {}
}

@main
struct ShellApp: App {
    var body: some Scene {
        WindowGroup { WebView() }
    }
}

Android 端(Kotlin) :

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val webView = WebView(this)
        webView.settings.javaScriptEnabled = true
        webView.loadUrl("https://your-h5-site.com")
        setContentView(webView)
    }
}

七、快速选型速查

追求性能 → Flutter > React Native > Ionic/Cordova > H5套壳
追求跨端(含小程序)→ UniApp / Taro
追求开发速度(已有H5)→ H5套壳(但功能受限)
需要原生API + 已有H5 → Ionic / Cordova
团队已有React → React Native
团队已有Vue → UniApp
只做 iOS → Swift
只做 Android → Kotlin

八、打包与发布

8.1 各技术打包产物概览

技术 iOS 产物 Android 产物 打包工具
Swift 原生 .ipa — Xcode
Kotlin 原生 — .apk / .aab Android Studio / Gradle
Flutter .ipa .apk / .aab flutter build
React Native .ipa .apk / .aab Xcode / Gradle / Expo
Ionic .ipa .apk / .aab ionic cap build / Xcode / Gradle
Cordova .ipa .apk / .aab cordova build / Xcode / Gradle
UniApp .ipa .apk / .aab HBuilderX 云打包 / 本地打包
Taro .ipa(RN端) .apk / .aab(RN端) 依赖 RN 打包流程
H5 套壳 .ipa .apk / .aab 取决于壳的编写方式

APK vs AAB :Google Play 自 2021 年 8 月起要求新应用必须使用 AAB(Android App Bundle)格式上传,AAB 会根据用户设备动态分发所需资源,体积更小。APK 仍可用于侧载或国内应用市场。


8.2 iOS 打包流程(所有技术通用)

前置条件
1. Apple Developer 账号($99/年,个人或公司)
2. Mac 电脑(Xcode 仅限 macOS)
3. 真机设备(用于测试,模拟器无法测试推送、相机等)
完整流程
各技术的 iOS 打包命令
flutter build ios --release



cd ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release archive


npx expo prebuild
npx expo run:ios --configuration Release

npx eas build --platform ios


cd ios && xcodebuild -workspace App.xcworkspace -scheme App -configuration Release archive


cordova build ios --release --device

8.3 Android 打包流程(所有技术通用)

前置条件
1. Android Studio
2. JDK 17+
3. 签名密钥(Release 版本必须)
完整流程
keytool -genkey -v \
  -keystore my-release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias my-alias

Gradle 签名配置(android/app/build.gradle 或 android/build.gradle):

android {
    signingConfigs {
        release {
            storeFile file("my-release-key.jks")
            storePassword "your-store-password"
            keyAlias "my-alias"
            keyPassword "your-key-password"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true      // 代码混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

生产环境不要把密码写死在代码里,使用环境变量或 local.properties:

# local.properties(不提交到 Git)
STORE_FILE=my-release-key.jks
STORE_PASSWORD=your-password
KEY_ALIAS=my-alias
KEY_PASSWORD=your-password



// build.gradle 中读取
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

signingConfigs {
    release {
        storeFile file(properties.getProperty('STORE_FILE'))
        storePassword properties.getProperty('STORE_PASSWORD')
        keyAlias properties.getProperty('KEY_ALIAS')
        keyPassword properties.getProperty('KEY_PASSWORD')
    }
}





./gradlew assembleRelease



./gradlew bundleRelease
各技术的 Android 打包命令
flutter build apk --release              
flutter build appbundle --release        


cd android && ./gradlew assembleRelease   
cd android && ./gradlew bundleRelease     


npx eas build --platform android          


cd android && ./gradlew assembleRelease


cordova build android --release

8.4 小程序打包(UniApp / Taro)

npm run build:mp-weixin    



npm run build:weapp        

8.5 签名与证书管理

平台 证书类型 有效期 丢失后果
iOS Distribution Certificate 1 年 需重新生成,不影响已上架 App
iOS Provisioning Profile 1 年 需重新生成,不影响已上架 App
Android Keystore (.jks) 25 年+ 永久丢失无法更新 App

Android 的 Keystore 一旦丢失,永远无法用相同包名发布更新 ,Google Play 和国内市场都要求相同的签名。务必备份到安全位置。


九、热更新方案

9.1 什么是热更新?

热更新 = 不经过应用商店审核,直接下发代码/资源更新到用户设备。

传统更新:发现 Bug → 修复 → 打包 → 提交审核 → 等待 1-3 天 → 用户下载更新
热更新:   发现 Bug → 修复 → 上传补丁 → 秒级生效 → 用户下次打开自动更新

9.2 各技术支持情况

技术 热更新支持 方案 限制
Swift 原生 ❌ 不支持 — Apple 禁止热更新原生代码
Kotlin 原生 ❌ 不支持 — Google 限制较少,但原生代码热更新也不推荐
Flutter ⚠️ 有限支持 shorebird、flutter_code_push 社区方案,非官方
React Native ✅ 支持 CodePush、Expo Updates JS Bundle 可热更新,原生模块不行
Ionic / Cordova ✅ 支持 CodePush、自定义实现 Web 资源可热更新
UniApp ✅ 支持 DCloud 云打包热更新 官方支持,WGT 资源包更新
Taro ⚠️ 有限支持 依赖 RN 端的热更新能力 H5/小程序端天然支持(就是网页)

9.3 React Native 热更新(CodePush)

npm install -g appcenter-cli


appcenter login


appcenter codepush release-react -a MyOrg/MyApp -d Production



import codePush from 'react-native-code-push';

function App() {
  
}

export default codePush({
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME
})(App);

9.4 UniApp 热更新

uni.request({
  url: 'https://your-server.com/check-update',
  success: (res) => {
    if (res.data.hasUpdate) {
      uni.downloadFile({
        url: res.data.wgtUrl,
        success: (downloadRes) => {
          uni.installUpdate({
            filePath: downloadRes.tempFilePath
          });
        }
      });
    }
  }
});

9.5 Apple 对热更新的限制

Apple App Store 审核指南 2.5.2:
"App 不得下载或安装可执行代码"

允许:
  ✅ JS 脚本解释执行(RN、WebView 内的 JS)
  ✅ 资源文件更新(图片、配置)
  ✅ 使用 Apple 的 JavaScriptCore 框架

禁止:
  ❌ 下载并执行原生机器码
  ❌ 使用 dlopen、dlsym 等动态加载
  ❌ 绕过审核机制更新核心功能

十、调试方式

10.1 各技术调试工具

技术 调试工具 断点调试 UI 检查 性能分析
Swift Xcode ✅ LLDB ✅ View Debugger ✅ Instruments
Kotlin Android Studio ✅ ✅ Layout Inspector ✅ Profiler
Flutter Flutter DevTools ✅ ✅ Widget Inspector ✅ Performance
React Native Chrome DevTools / Flipper ✅ ✅ Element Inspector ✅ Hermes Profiler
Ionic Chrome DevTools ✅ ✅ ❌(依赖浏览器工具)
UniApp HBuilderX / 微信开发者工具 ❌ ✅ ❌
Taro 微信开发者工具 / Chrome ❌ ✅ ❌

10.2 真机调试

10.3 日志查看

idevicesyslog | grep MyApp


adb logcat -s "MyApp:D"    
adb logcat | grep flutter   
adb logcat | grep ReactNativeJS  

十一、鸿蒙 HarmonyOS(补充)

11.1 鸿蒙开发技术

技术 说明 适用场景
ArkTS(原生) 鸿蒙官方语言,TypeScript 超集 追求最佳性能和体验
ArkUI(声明式 UI) 类似 SwiftUI / Flutter 的声明式语法 鸿蒙原生 App
元服务(Atomic Service) 免安装、卡片化 轻量服务
跨平台框架适配 Flutter、RN 已有鸿蒙适配版本 已有跨平台项目迁移

11.2 最小启动步骤(ArkTS)

最小 ArkTS 代码(Index.ets):

@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Hello, HarmonyOS!')
        .fontSize(24)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

11.3 鸿蒙打包