You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native多应用共用JS代码:原生层多应用适配方案咨询

兄弟,我太懂这种不想复制粘贴原生代码的痛苦了!之前我用同一套JS核心做了3个不同主题的App,原生端完全没复制代码,都是靠构建配置和资源隔离搞定的,给你分享几个实用方案:

iOS端方案

1. Build Configuration + Info.plist 参数注入

这是最轻量化的方案,适合主题差异不大的场景:

  • 首先在Xcode里创建多个Build Configuration(比如AppA_Debug、AppA_Release、AppB_Debug、AppB_Release),复制默认的Debug/Release配置就行。
  • 在Info.plist里添加自定义字段(比如AppTheme),然后通过Xcode的Build Settings,给不同的Configuration设置不同的参数值(可以用$(APP_THEME)这种变量,再在xcconfig文件里统一管理)。
  • 原生代码里读取这个参数,加载对应主题资源,同时注入给JS:
// Swift 示例
func setupThemeAndJS() {
    guard let theme = Bundle.main.object(forInfoDictionaryKey: "AppTheme") as? String else {
        return
    }
    // 加载主题对应的颜色、图片资源
    switch theme {
    case "ThemeA":
        view.backgroundColor = UIColor(named: "ThemeA_MainBg")
    case "ThemeB":
        view.backgroundColor = UIColor(named: "ThemeB_MainBg")
    default:
        break
    }
    // 给WebView注入主题参数,确保JS加载前就能拿到
    let userScript = WKUserScript(
        source: "window.appTheme = '\(theme)';",
        injectionTime: .atDocumentStart,
        forMainFrameOnly: true
    )
    webView.configuration.userContentController.addUserScript(userScript)
}

2. 多Target + 资源分组

如果不同App的资源(图标、启动页、颜色)差异很大,可以创建多个Target,但共享99%的代码:

  • 在Xcode里右键项目 -> New Target,选择iOS App,创建AppA、AppB等Target。
  • 把通用代码拖到所有Target里(或者更优雅的方式:抽成一个Framework,让所有Target依赖它)。
  • 每个Target关联独立的Asset Catalog(比如AppA.xcassets、AppB.xcassets),里面放对应主题的资源,同名资源会自动匹配。
  • 用预编译宏区分Target,比如在Build Settings的Preprocessor Macros里给AppA加APP_TARGET_A=1,AppB加APP_TARGET_B=1,代码里判断:
#if APP_TARGET_A
private let currentTheme = "ThemeA"
#elseif APP_TARGET_B
private let currentTheme = "ThemeB"
#endif

Android端方案

1. Product Flavors + Build Config

Android的Product Flavors简直是为这种场景量身定做的!

  • 在Module级别的build.gradle里定义不同的Flavor:
android {
    flavorDimensions "app"
    productFlavors {
        appA {
            dimension "app"
            // 注入主题参数到BuildConfig
            buildConfigField "String", "APP_THEME", "\"ThemeA\""
            // 自定义App名称、图标等资源
            resValue "string", "app_name", "我的App A"
            manifestPlaceholders = [appIcon: "@mipmap/ic_launcher_a"]
        }
        appB {
            dimension "app"
            buildConfigField "String", "APP_THEME", "\"ThemeB\""
            resValue "string", "app_name", "我的App B"
            manifestPlaceholders = [appIcon: "@mipmap/ic_launcher_b"]
        }
    }
}
  • 原生代码里直接用BuildConfig.APP_THEME获取参数,加载资源并注入JS:
// Kotlin 示例
fun setupThemeAndWebView() {
    val theme = BuildConfig.APP_THEME
    // 加载对应主题的颜色
    val mainColor = when(theme) {
        "ThemeA" -> ContextCompat.getColor(this, R.color.theme_a_main)
        "ThemeB" -> ContextCompat.getColor(this, R.color.theme_b_main)
        else -> ContextCompat.getColor(this, R.color.default_main)
    }
    // 给WebView注入主题参数
    webView.evaluateJavascript("window.appTheme = '$theme';") { _ ->
        webView.loadUrl("file:///android_asset/index.html")
    }
}
  • 每个Flavor可以有自己的资源目录(比如src/appA/res/colors.xml),同名资源会自动覆盖默认资源,不用改代码。

2. 核心库抽离

不管用哪种方案,都建议把通用的原生代码(比如WebView封装、网络请求工具)抽成一个Android Library Module,让所有Flavor依赖这个库,只在App Module里处理主题相关的差异,这样核心代码只维护一份,非常省心。

通用建议

  • JS和原生的参数命名要统一(比如都用appTheme),避免两边逻辑混乱。
  • 测试时,iOS切换Scheme就能测试不同配置,Android直接在Build Variants里选对应的Flavor,效率很高。
  • 如果有针对特定主题的额外原生操作,可以把逻辑封装成主题策略类,根据参数动态初始化,比如iOS用ThemeProtocol,Android用接口实现,避免大量if-else。

内容的提问来源于stack exchange,提问作者alimek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:08:32