React Native 构建错误:文本不能为空或为空
Posted
技术标签:
【中文标题】React Native 构建错误:文本不能为空或为空【英文标题】:React Native build error: Text must not be null or empty 【发布时间】:2019-12-09 09:14:11 【问题描述】:我的 Jenkins 版本给了我以下错误:
13:18:22 FAILURE: Build failed with an exception.
13:18:22
13:18:22 * Where:
13:18:22 Script '/Users/abcd/Jenkins/Jenkins-Workspaces/ABCD/ABCDL/node_modules/@react-native-community/cli-platform-android/native_modules.gradle' line: 190
13:18:22
13:18:22 * What went wrong:
13:18:22 A problem occurred evaluating settings 'AppName'.
13:18:22 > Text must not be null or empty
13:18:22
似乎问题出在@react-native-community/cli-platform
节点模块上,但请阅读这个已关闭的问题:
https://github.com/facebook/react-native/issues/25479
我不清楚提出的和最终的解决方案到底是什么。
在这个 react-native 问题中有一个更直接的修复建议: https://github.com/facebook/react-native/issues/25822
但我的错误不是抱怨那条线。
至于安装@react-native-community/cli
,我相信我的package-lock.json
文件中已经有了它:
"react-native":
"version": "0.60.4",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.60.4.tgz",
"integrity": "sha512-WE41lbGQjnzM9srIFtMDtMJkQAvk95iZwuFvAxl68s80bkYa7Ou9sGFHpeYIV6cY8yHtheCSo5q6YMxhdfkdOw==",
"requires":
"@babel/runtime": "^7.0.0",
"@react-native-community/cli": "^2.0.1",
"@react-native-community/cli-platform-android": "^2.0.1",
"@react-native-community/cli-platform-ios": "^2.0.1",
其他人提到了一些关于app/build.gradle
的事情,这是我的相关部分:
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy)
from configurations.compile
into 'libs'
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
还提到了android/settings.gradle
,这个是我的:
rootProject.name = 'NFIBEngage'
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':appcenter-crashes'
project(':appcenter-crashes').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-crashes/android')
include ':appcenter-analytics'
project(':appcenter-analytics').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-analytics/android')
include ':appcenter'
project(':appcenter').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
根据我在这里收集的内容:
https://react-native-community.github.io/upgrade-helper/?from=0.53.3&to=0.60.4
以上文件正确。
那么这里到底出了什么问题,我该如何解决呢?
就node_modules/@react-native-community/cli-platform-android/native_modules.gradle line 190
来说是这个:
def json = new JsonSlurper().parseText(reactNativeConfigOutput)
问题可能出在我如何编写 index.js 文件:
/**
* @format
*/
import AppRegistry from "react-native";
// old config code
import KeyboardManager from "react-native-keyboard-manager";
// old config code ^^^
import NFIBEngage from "./App";
import name as appName from "./app.json";
// old config code
import Sentry from "react-native-sentry";
Sentry.config(
"https://asdf@sentry.io/123456677"
).install();
KeyboardManager.setToolbarPreviousNextButtonEnable(true);
// old config code ^^^
AppRegistry.registerComponent("NFIBEngage", () => NFIBEngage);
AppRegistry.registerComponent()
写对了吗?
我在本地运行了 Jenkins 脚本,我相信这个脚本就在这里:
import fs from "fs-extra";
import eachSeries from "async/eachSeries";
import exec from "child_process";
import androidDirectory from "../../app.json";
import resolveFromRoot, distDir, createLogger from "../build";
const logger = createLogger("android");
const APK_PATTERN = /release\.apk$/i;
function copyArtifactsToDist()
logger.logHeader("Copying APK to Dist", repeatChar: "=" );
const baseDir = `$androidDirectory/app/build/outputs/apk`;
const allFlavs = ["dev", "qa", "ua", "prod"];
const branchName = process.env.GitVersion_BranchName || "";
const buildFlavour = branchName.startsWith("release/") ? allFlavs : ["dev"];
const envs =
dev: "INT",
qa: "QA",
ua: "UA",
prod: ""
;
buildFlavour
.map(env =>
const apkOutputDir = resolveFromRoot(`$baseDir/$env/release`);
return
apkOutputDir,
env
;
)
.forEach(( apkOutputDir, env ) =>
const src = `$apkOutputDir/app-$env-release.apk`;
//prettier-ignore
const binaryName = env === 'prod' ? 'ENGAL.apk' : `ENGAL-$envs[env].apk`;
const dest = `$distDir/$binaryName`;
fs.copy(src, dest, (err: Error) =>
if (err)
logger.error(err);
);
);
function run()
logger.logHeader("Starting Android Builds", repeatChar: "#" );
const flavours = [
endpoint: "dv",
flavour: "Dev",
appcenterKey: "<hashKeys>"
,
endpoint: "qa",
flavour: "Qa",
appcenterKey: "<hashKeys>"
,
endpoint: "ua",
flavour: "Ua",
appcenterKey: "<hashKeys>"
,
endpoint: "prod",
flavour: "Prod",
appcenterKey: "<hashKeys>"
];
const versionCode = process.env.Build || 1;
const release = process.env.GitVersion_MajorMinorPatch || "1.0.0";
const fullAppVersion = `$release-$versionCode`;
const devFlav = flavours.find(f => f.flavour.toLocaleLowerCase() === "dev");
const branchName = process.env.GitVersion_BranchName || "";
const buildFlavour = branchName.startsWith("release/") ? flavours : [devFlav];
eachSeries(
buildFlavour,
(f, callback) =>
//prettier-ignore
logger.logHeader(
`starting gradle assemble$f.flavourRelease with flag - versionName=$fullAppVersion -PversionCode=$versionCode`,
repeatChar: '-'
);
const engaInfo = `ENGAGE_VERSION=$fullAppVersion`;
const engaEndpoint = `ENGAGE_ENDPOINT=$f.endpoint`;
const engaCenter = `APPCENTER_KEY=$f.appcenterKey`;
const engaPlatform = "APPCENTER_PLATFORM=android";
//prettier-ignore
const prepare = `$engaEndpoint $engaCenter $engaInfo $engaPlatform npm run setup`;
const cd = `cd $androidDirectory`;
//prettier-ignore
const releaseCmd = `./gradlew assemble$f.flavourRelease -PversionName=$fullAppVersion -PversionCode=$versionCode && cd ..`;
exec(`$prepare && $cd && $releaseCmd`, err =>
if (err)
return callback(err);
logger.logHeader(`$f.flavour Android Build Successful!`,
repeatChar: "#"
);
logger.close();
callback(null);
);
,
error =>
if (error)
logger.logHeader("Android Builds Failed!",
repeatChar: "#"
);
logger.error(error);
logger.close();
copyArtifactsToDist();
);
run();
通过npm run build
在本地我收到此错误:
FAILURE: Build failed with an exception.
* What went wrong:
Task 'assembleDevRelease' not found in root project 'AppName'. Some candidates are: 'assembleRelease'.
这些是相关的错误吗?任何有 React Native 构建经验的人?
按照建议,我查看了我的 android/app/build.gradle
文件中的 productFlavors
并注意到它们确实在此处丢失了:
buildTypes
debug
signingConfig signingConfigs.debug
release
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
// applicationVariants are e.g. debug, release
applicationVariants.all variant ->
variant.outputs.each output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 123456 + defaultConfig.versionCode
所以我是这样添加的:
buildTypes
debug
signingConfig signingConfigs.debug
release
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
productFlavors
dev
resValue "string", "app_name", getAppName("INT")
resValue "string", "link_launcher", getLauncher("dv")
applicationIdSuffix ".dv"
manifestPlaceholders = [onesignal_app_id: "<hash_id>",
onesignal_google_project_number: "123456789"]
qa
resValue "string", "app_name", getAppName("QA")
resValue "string", "link_launcher", getLauncher("qa")
applicationIdSuffix ".qa"
manifestPlaceholders = [onesignal_app_id: "<hash_id>",
onesignal_google_project_number: "123456789"]
ua
resValue "string", "app_name", getAppName("UA")
resValue "string", "link_launcher", getLauncher("ua")
applicationIdSuffix ".ua"
manifestPlaceholders = [onesignal_app_id: "<hash_id>",
onesignal_google_project_number: "123456789"]
prod
resValue "string", "app_name", getAppName()
resValue "string", "link_launcher", getLauncher()
manifestPlaceholders = [onesignal_app_id: "<hash_id>",
onesignal_google_project_number: "601125149914"]
// applicationVariants are e.g. debug, release
applicationVariants.all variant ->
variant.outputs.each output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
buildTypes
看起来与原来的旧版buildTypes
有点不同,所以我不确定这是否可以,但无论如何我在本地再次运行 npm run build
并收到此错误:
* Where:
Build file '/Users/danale/Projects/NFIBEngage/android/app/build.gradle' line: 168
* What went wrong:
A problem occurred evaluating project ':app'.
> Could not find method getAppName() for arguments [INT] on ProductFlavor_Decoratedname=dev, dimension=null, minSdkVersion=null, targetSdkVersion=null, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=null, versionName=null, applicationId=null, testApplicationId=null, testInstrumentationRunner=null, testInstrumentationRunnerArguments=, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields=, mResValues=, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders=, mWearAppUnbundled=null of type com.android.build.gradle.internal.dsl.ProductFlavor.
我能够通过添加缺少的方法来解决本地错误,如下所示:
def appName = "Engage";
/**
* Get the version name from command line param
*
* @return int If the param -PversionName is present then return int value or -1
*/
def getAppName = env ->
return (env ? appName + " ("+ env + ")" : appName);
/**
* Get the version name from command line param
*
* @return int If the param -PversionName is present then return int value or -1
*/
def getLauncher = env ->
return (env ? "engage-" + env + ".nfib.org" : "engage.nfib.org");
android
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
flavorDimensions "default"
defaultConfig
applicationId "com.nfib.engage"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
splits
abi
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
signingConfigs
debug
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
buildTypes
debug
signingConfig signingConfigs.debug
release
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
productFlavors
dev
dimension 'default'
resValue "string", "app_name", getAppName("INT")
resValue "string", "link_launcher", getLauncher("dv")
applicationIdSuffix ".dv"
manifestPlaceholders = [onesignal_app_id: "b78285eb-f1ec-46f3-9ad0-c7efe691a401",
onesignal_google_project_number: "584236827312"]
qa
dimension 'default'
resValue "string", "app_name", getAppName("QA")
resValue "string", "link_launcher", getLauncher("qa")
applicationIdSuffix ".qa"
manifestPlaceholders = [onesignal_app_id: "e4280f5e-62ec-41a4-bd86-f5b94e471a36",
onesignal_google_project_number: "162802054510"]
ua
dimension 'default'
resValue "string", "app_name", getAppName("UA")
resValue "string", "link_launcher", getLauncher("ua")
applicationIdSuffix ".ua"
manifestPlaceholders = [onesignal_app_id: "2ffd8dc0-9c6b-4035-999d-fc694194725a",
onesignal_google_project_number: "594905904045"]
prod
dimension 'default'
resValue "string", "app_name", getAppName()
resValue "string", "link_launcher", getLauncher()
manifestPlaceholders = [onesignal_app_id: "82dcb42f-1d35-4b79-bc28-2d1d02dbda36",
onesignal_google_project_number: "601125149914"]
不幸的是,我在 Jenkins 中继续遇到同样的错误。
【问题讨论】:
检查你的 react-native-community/cli 是否是最新版本。它在 35 分钟前更新。 link @firats,我的项目中什至没有那个包:✗ npm ls @react-native-community/cli NFIBEngage@0.0.1 /Users/danale/Projects/NFIBEngage └── (empty)
实际上您链接中的一些 cmets 指向安装 @react-native-community/cli 作为解决方案。你试过了吗?
@firats,我相信我在刚刚添加的内容中解决了您的问题。
从您的 package.json 中,您的 cli
版本位于 ^2.0.1
和 2.0.1
确实是存在您从 github.com/facebook/react-native/issues/25479 链接到的问题的 cli 版本您是否验证过您的node_modules/@react-native-community/cli-platform-android/native_modules.gradle
中类似于def command = "../node_modules/.bin/react-native config"
(来自github.com/facebook/react-native/issues/…)的行是否正确?您还应该确保安装的 cli 版本 >= 2.0.2。
【参考方案1】:
来自 cmets 的一些使构建工作的更改:
从您的 package.json 中,您的 cli 版本位于 ^2.0.1
和 2.0.1
确实是存在您从 github.com/facebook/react-native/issues/25479 链接到的问题的 cli 版本您确认node_modules/@react-native-community/cli-platform-android/native_modules.gradle
中类似于def command = "../node_modules/.bin/react-native config"
(来自github.com/facebook/react-native/issues/...)的行是正确的?您还应该确保您安装的 cli 版本 >= 2.0.2
。
确保您在android/app/build.gradle
中的buildTypes
和productFlavors
定义设置为包含您尝试在jenkins 工作中构建的所有不同变体。看起来你有 dev
、qa
、ua
和 prod
的口味。查看 gradle 文档 developer.android.com/studio/build/build-variants#build-types 了解更多信息。
您的build.gradle
中似乎缺少getAppName
函数。像ext.getAppName = suffix = '' -> 'MyAppName' + suffix
这样的东西。快速扫描您的 build.gradle
看起来您需要另一个名为 getLauncher
的字符串,它会为您使用 link_launcher
的任何内容返回一个适当的字符串。
【讨论】:
后面部分已经解决了,我加了def getAppName = env ->
和def getLauncher = env ->
,但是Jenkins中问题依旧。我会更新 OP。
关于cli
的版本,当我尝试这样做时,即使我将其物理更改为2.0.2
,它也会继续安装相同的版本。
你在哪里改?在package-lock.json
中的@react-native-community/cli
条目中?我通常使用 yarn
并且没有使用 npm 的内置锁定文件的经验,但请确保您更改的是 cli 包的条目,而不是 react-native
下的条目。
我从package-lock.json
文件中删除它并运行npm install
,然后我返回并手动将其更改为所需的版本并运行npm install
,两次都安装了我已经拥有的版本.
今天我注意到我的node_modules
中根本没有@react-native-community/cli
【参考方案2】:
我在我的 CI 工具上升级了我的节点版本并修复了这个确切的错误。 我之前是第 6 版,后来升级到了 10
【讨论】:
我使用的是节点版本 11,我最近不得不将其降级到 10 才能使用expo-cli
。【参考方案3】:
我也遇到过这个问题
很容易解决这个问题
移除节点模块
和
重新安装 node_module : npm install
react-native run-android
【讨论】:
以上是关于React Native 构建错误:文本不能为空或为空的主要内容,如果未能解决你的问题,请参考以下文章
React Native Expo - Jest - React Native Firebase - Invariant Violation:Native 模块不能为空
在使用 React Native 的 IOS 运行时出现“未处理的 JS 异常:本机模块不能为空”错误
不变违规:本机模块不能为空。 React Native Firebase 应用程序