背景 我们业务的 SDK 包含 ReactNative 方案,所以必须依赖 React Native 的 AAR,但是最近对接的客户有自己依赖的版本,和我们使用的版本不同,所以需要我们的 React Native 代码运行在他们使用的版本上。
问题 当 React Native 版本和 Native 版本不一致时,会弹出红框提示
React Native version mismatch. JavaScript version:0.xx.x Native Version:0.xx.x
解决方法 根据提示在源码里搜索发现,来自于Libraries/Core/ReactNativeVersionCheck.js 这个文件里,根据文件注释可以看出是专门做版本校验
ReactNativeVersionCheck.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 exports .checkVersions = function checkVersions ( ): void { const nativeVersion = Platform .constants .reactNativeVersion ; if ( ReactNativeVersion .version .major !== nativeVersion.major || ReactNativeVersion .version .minor !== nativeVersion.minor ) { console .error ( `React Native version mismatch.\n\nJavaScript version: ${_formatVersion( ReactNativeVersion.version, )} \n` + `Native version: ${_formatVersion(nativeVersion)} \n\n` + 'Make sure that you have rebuilt the native code. If the problem ' + 'persists try clearing the Watchman and packager caches with ' + '`watchman watch-del-all && react-native start --reset-cache`.' , ); } };
可以看出如果是 path 兼容版本则不会弹框提示,非兼容版本时会弹框警告,如果要想去掉弹框提示,则直接注释掉这个校验代码,再使用命令行重新打包 js 代码即可。
探究 根据上面代码可以看出,根据命名大概可以猜出ReactNativeVersion
是 js 侧的版本号, Platform.constants.reactNativeVersion
是 Native 侧的版本号。 从 ReactNativeVersionCheck 文件的导包可以看到他们的定义目录
ReactNativeVersionCheck.js 1 2 import Platform from '../Utilities/Platform' ;const ReactNativeVersion = require ('./ReactNativeVersion' );
通过搜索源码发现 ReactNativeVersionCheck.js->Platform.android.js->NativePlatformConstantsAndroid.js(PlatformConstants)->AndroidInfoModule.java->ReactNativeVersion.java 在这里我们发现了定义的地方
ReactNativeVersion.java 1 2 3 4 5 6 7 public class ReactNativeVersion { public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of( "major" , 0 , "minor" , 0 , "patch" , 0 , "prerelease" , null ); }
但是都是 0 还未赋值,看到有这样的注释* @generated by scripts/bump-oss-version.js
,原来是通过脚本动态赋值的。 查看脚本发现
bump-oss-version.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 26 27 28 29 30 31 32 33 34 35 36 37 38 fs.writeFileSync ( 'ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java' , cat ('scripts/versiontemplates/ReactNativeVersion.java.template' ) .replace ('${major}' , major) .replace ('${minor}' , minor) .replace ('${patch}' , patch) .replace ( '${prerelease}' , prerelease !== undefined ? `"${prerelease} "` : 'null' , ), 'utf-8' , ); fs.writeFileSync ( 'ReactCommon/cxxreact/ReactNativeVersion.h' , cat ('scripts/versiontemplates/ReactNativeVersion.h.template' ) .replace ('${major}' , major) .replace ('${minor}' , minor) .replace ('${patch}' , patch) .replace ( '${prerelease}' , prerelease !== undefined ? `"${prerelease} "` : '""' , ), 'utf-8' , ); fs.writeFileSync ( 'Libraries/Core/ReactNativeVersion.js' , cat ('scripts/versiontemplates/ReactNativeVersion.js.template' ) .replace ('${major}' , major) .replace ('${minor}' , minor) .replace ('${patch}' , patch) .replace ( '${prerelease}' , prerelease !== undefined ? `'${prerelease} '` : 'null' , ), 'utf-8' , );
分别给 js,Android,iOS 赋值的代码。到这里我们就了解了 React Native 版本校验的逻辑。通过脚本动态生成三端的版本号。
疑惑 在 bump-oss-version.js 里发现这段代码,感觉挺难理解为啥要做这样的限制。
bump-oss-version.js 1 2 3 4 5 6 7 8 9 let version = argv._ [0 ];if (!version || version.indexOf (versionMajor) !== 0 ) { echo ( `You must pass a tag like 0.${versionMajor} .[X]-rc[Y] to bump a version` , ); exit (1 ); }