編譯打包篇 — 靈活使用BuildConfig

看完本篇將了解到:
第一,如何在BuildConfig文件中構(gòu)建自定義的屬性;
第二,如何利用命令行修改這些自定義屬性,從而構(gòu)建不同版本的安裝包。(比如正式環(huán)境帶Log日志打印的包等等)

1 起因

最近翻看公司項(xiàng)目的時(shí)候,看到了以下代碼

import Config from 'react-native-config';

const developConfig = {
  api: {
    protocol: 'http',
    host: 'test-api.anystories.app',
  }, 
};

const releaseConfig = {
  api: {
    protocol: 'https',
    host: "api.anybooks.live",
  },
};

let config = releaseConfig;

// 對(duì),就是這一行代碼,說(shuō)得就是你
if (Config.ENV === "dev" || __DEV__) {
  config = developConfig;
}

export {
  config,
};

注意上面那行被標(biāo)記的代碼,是不是有點(diǎn)好奇,這個(gè)config.ENV中的ENV是怎么來(lái)?

2 react-native-config的使用簡(jiǎn)介

于是乎就去了解react-native-config的用法,官網(wǎng)地址如下:react-native-config官網(wǎng)。

先簡(jiǎn)單介紹一下它的用法,先在項(xiàng)目根目錄定義一個(gè)文件叫做.dev,然后在文件中隨便定義幾個(gè)變量:

API_URL=https://myapi.com
GOOGLE_MAPS_API_KEY=abcdefgh

獲取變量的方法如下:

import Config from "react-native-config";
 
Config.API_URL; // 'https://myapi.com'
Config.GOOGLE_MAPS_API_KEY; // 'abcdefgh'

此時(shí),應(yīng)該能明白ENV其實(shí)就是我們?cè)?code>.dev文件中定義的一個(gè)變量,其實(shí)這是RN與Android交互中暴露出來(lái)的常量值,往后有機(jī)會(huì)再做一下介紹。

3 為何出現(xiàn)在BuildConfig.java文件中

而后,又發(fā)現(xiàn)一個(gè)問(wèn)題,這個(gè)在.dev文件中定義的變量,會(huì)直接出現(xiàn)在Android編譯項(xiàng)目時(shí)產(chǎn)生的BuildConfig.java文件中。

buildconfig.png

這成功又勾起了我的好奇心,為啥在.dev文件中的變量會(huì)出現(xiàn)在BuildConfig.java文件中呢?

這就得看這個(gè)RN庫(kù)的Android端代碼做了什么,于是去找到源碼,這個(gè)得從Android項(xiàng)目中build.gradle構(gòu)建腳本中說(shuō)起。在我們使用react-native-config庫(kù)后,在build.gradle中會(huì)引入如下一行代碼:

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

這里是直接把dotenv.gradle腳本引入,然后我們找到dotenv.gradle文件,里面有段腳本如下:

def loadDotEnv(flavor = getCurrentFlavor()) {
    def envFile = ".env"

    if (System.env['ENVFILE']) {
        envFile = System.env['ENVFILE']
        println("zp_test system env")
    } else if (System.getProperty('ENVFILE')) {
        envFile = System.getProperty('ENVFILE')
        println("zp_test system getProperty")
    } else if (project.hasProperty("envConfigFiles")) {
        // use startsWith because sometimes the task is "generateDebugSources", so we want to match "debug"
        project.ext.envConfigFiles.any { pair ->
            if (flavor.startsWith(pair.key)) {
                envFile = pair.value
                return true
            }
        }
    } else if (project.hasProperty("defaultEnvFile")) {
        envFile = project.defaultEnvFile
    }

   ...
}

loadDotEnv()

android {
    defaultConfig {
        project.env.each { k, v ->
            def escaped = v.replaceAll("%","\\\\u0025")
            buildConfigField "String", k, "\"$v\""
            resValue "string", k, "\"$escaped\""
        }
    }
}

以上腳本文件就不一一解釋了,大致的邏輯就是:

1 在系統(tǒng)環(huán)境變量中去找尋一個(gè)名叫ENVFILE的環(huán)境變量,如果存在就直接賦值給環(huán)境變量。
2 如果不存在就查看系統(tǒng)屬性中是否存在。
3 如果不存在就查看項(xiàng)目的defaultEnvFile屬性。
4 找到并遍歷這個(gè)文件,寫(xiě)入BuildConfig中。

寫(xiě)入到buildconfig中的代碼:

buildConfigField "String", k, "\"$v\""

三個(gè)參數(shù)依次為寫(xiě)入的字段類型,寫(xiě)入的字段名,寫(xiě)入的字段值。而指定環(huán)境變量,這里涉及到一個(gè)命令行:export xxx=.dev;這時(shí)環(huán)境變量xxx就被指定了,此時(shí)編譯打包xxx環(huán)境變量就會(huì)一直指向.dev。比如上面代碼中的ENVFILE。

4 總結(jié)

第一步,寫(xiě)好腳本文件獲取自定義環(huán)境變量(比如ENVFILE),腳本文件主要有兩個(gè)作用

  • 第一,找到環(huán)境變量所指文件;
  • 第二,遍歷文件中的所有字段,并利用buildConfigField "String", k, "\"$v\""這句代碼將文件中的值寫(xiě)入到BuildConfig中去。

第二步,用export命令指定當(dāng)前ENVFILE為哪個(gè)文件,比如export ENVFILE=.env。

第三步,編譯打包;

此時(shí),就算打release包,也可以利用export命令指定相應(yīng)變量的值至BuildConfig中去,達(dá)到動(dòng)態(tài)改變配置的效果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容