内容简介:最近一段时间一直在写 RN 的项目,期间遇到了挺多的坑,然后想着记录一下填坑的过程(想看答案的小伙伴可以忽略我的心厉路程,直接跳到结尾总结处)。于是乎,第一步,赶紧新建一个demo,飞快地在 terminal 中输入因为比较懒(这句话在我的博客中出现的次数不低,懒是万恶之源,罪过罪过~~),不想升级,再配置一系列东西,所以按照 中文网 给出的创建指定版本的方法:
最近一段时间一直在写 RN 的项目,期间遇到了挺多的坑,然后想着记录一下填坑的过程(想看答案的小伙伴可以忽略我的心厉路程,直接跳到结尾总结处)。
step1. 我竟然偷偷的给自己挖了个坑?
于是乎,第一步,赶紧新建一个demo,飞快地在 terminal 中输入 react native init yx_rnDemo
,漫长的等待后,项目成功建立。 然后用 IDE 打开 demo ,执行 react-native run-android
命令,结果半路夭折,没跑起来。仔细一看错误日志,发现 android 各种依赖都下载失败。然后看了下 package.json
中 react-native 的版本,发现引用的是最新版本,然后点击查看 android 文件夹,发现引用的 gradle 版本是 3.1.4 ,然鹅我用的还是 2.3.3 的版本。。
因为比较懒(这句话在我的博客中出现的次数不低,懒是万恶之源,罪过罪过~~),不想升级,再配置一系列东西,所以按照 中文网 给出的创建指定版本的方法:
提示:你可以使用--version参数(注意是两个杠)创建指定版本的项目。例如react-native init MyApp --version 0.44.3。注意版本号必须精确到两个小数点
删掉 demo ,重新输入 react native init yx_rnDemo --version0.47.2
,结果最后发现其实创建的还是最新版。。(内心 OS,what??其实细心的朋友估计已经发现问题了,哈哈,嘘~~)
然后开始各种面向搜索引擎,发现大家都是这样创建的啊,并且 RN 官网上给出的命令也是这样的,为什么别人没有问题,到我这就有问题了呢。
然后换了一个命令执行: react-native init yx_rnDemo --verbose --version 0.47.2
想来看一下创建项目的详细信息,结果最后显示创建的竟然是对的!! 就是 0.47.2 。
难道说加了一个 --verbose
条件就能创建成功了?不对啊,我看了下说 --verbose
条件只是会输出详细信息的啊,照理说不应该对结果产生什么影响的。然后不信邪的我把 --verbose
命令去掉,又执行了 react-native init yx_rnDemo --version 0.47.2
,过了一会发现,竟然也是对的!!
吓得我赶紧去翻我第一次写的命令,一对比,发现我第一个命令 --verison
后没有换行~~
第一次的:react native init yx_rnDemo --version0.47.2 第二次的:react-native init yx_rnDemo --version 0.47.2
本来到这就可以结束的,然而作为一个想有灵魂的程序猿,还是很想弄清楚为什么不加空格就会创建最新版本,而不是提示语法错误的原因。
step2. 一步步分析坑是如何产生的
这里首先介绍一下, react-native 源码中 react-native-cli 文件夹下的 index.js 这个文件很重要,它唯一的工作是初始化存储库,然后将所有命令转发到本地的 react-native 版本。所以我们初始化项目时做的操作可以在这个文件中找到。
打开这个 js 文件,然后开始一探究竟吧。 1.
'use strict'; var fs = require('fs'); var path = require('path'); var exec = require('child_process').exec; var execSync = require('child_process').execSync; var chalk = require('chalk'); var prompt = require('prompt'); var semver = require('semver'); /** * Used arguments: * -v --version - to print current version of react-native-cli and react-native dependency * if you are in a RN app folder * init - to create a new project and npm install it * --verbose - to print logs while init * --template - name of the template to use, e.g. --template navigation * --version <alternative react-native package> - override default (https://registry.npmjs.org/react-native@latest), * package to install, examples: * - "0.22.0-rc1" - A new app will be created using a specific version of React Native from npm repo * - "https://registry.npmjs.org/react-native/-/react-native-0.20.0.tgz" - a .tgz archive from any npm repo * - "/Users/home/react-native/react-native-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests */ var options = require('minimist')(process.argv.slice(2)); 复制代码
文件的前 62 行都是在声明变量及引用,其中有几个变量这里我们需要知道它们是的作用:
变量名 | 含义 |
---|---|
fs | Node.js 中 文件系统操作的模块 |
path | Node.js 中用于处理文件路径的小 工具 的模块 |
exec | Node.js 中子进程模块, 衍生一个 shell 并在 shell 上运行命令 |
execSync | exec 的同步函数,会阻塞 Node.js 事件循环 |
chalk | 定制控制台日志的输入样式的一个插件 |
prompt | node 命令行输入控件 |
semver | semver 语义化版本号 |
options | 轻量级的命令行参数解析工具 |
其中一个很关键的变量 options ,也就是引用的 require('minimist')(process.argv.slice(2))
,是一个命令行参数解析工具,具体的介绍可以参考这里,它是以键值对进行解析的。比如我们输入的命令行是: react-native init yx_rnDemo --version 0.47.2
,其中 --version 0.47.2
就是一个可解析的键值对,key 为 version , value 为 0.47.2 。
这个文件中,我们有用到的键值对的值在截图的注释中可以看到:
-
-v
: 打印当前 react-native-cli 的版本和 react native 的依赖关系 -
init
: 创建一个新工程并且执行 npm install -
--verbose
:init
时添加的参数,打印init
时的参数 - -
-template
:用到的模板的名称 -
--version
: 会覆盖默认(最新版本)安装的 react-native 的版本。 也就是如果要创建指定版本的,需要加上这个参数
OK, 各个变量的含义我们都弄清楚了,下面让我们继续探究~~
2.
switch (commands[0]) { case 'init': if (!commands[1]) { console.error('Usage: react-native init <ProjectName> [--verbose]'); process.exit(1); } else { init(commands[1], options); } break; default: //...代码省略 break; } } 复制代码
在这之前 116 行 定义了 commands 这个变量,取值的结果是解析的参数,应该是 _ [ 'init ', 'yx_rnDEmo']
,所以会走switch 的第一个选项,去执行 init(commands[1], options)
方法,参数为 'yx_rnDemo’ 和 options 变量。
3.
/** * @param name Project name, e.g. 'AwesomeApp'. * @param options.verbose If true, will run 'npm install' in verbose mode (for debugging). * @param options.version Version of React Native to install, e.g. '0.38.0'. * @param options.npm If true, always use the npm command line client, * don't use yarn even if available. */ function init(name, options) { validateProjectName(name); if (fs.existsSync(name)) { createAfterConfirmation(name, options); } else { createProject(name, options); } } 复制代码
很简单,先去判断我们起的工程名称是否符合命名规范,并且判断是否存在。所以下面直接看 createProject(name, options)
方法
4.
function createProject(name, options) { //....代码省略 run(root, projectName, options); } 复制代码
这个方法里主要是去进行创建工程文件夹和 package.json 文件的操作,然后后续行动在 run(root, projectName, options)
函数中
5.
function run(root, projectName, options) { var rnPackage = options.version; // e.g. '0.38' or '/path/to/archive.tgz' console.log('Installing ' + getInstallPackage(rnPackage) + '...'); //...代码省略 installCommand = 'npm install --save --save-exact ' + getInstallPackage(rnPackage); if (options.verbose) { installCommand += ' --verbose'; } //...代码省略 try { execSync(installCommand, {stdio: 'inherit'}); } catch (err) { //... 代码省略 } cli.init(root, projectName); } 复制代码
其中这个 rnPackage
就是解析的 version 参数 ,所以,对于我的第一次使用的命令: react-native init yx_rnDemo --version0.47.2
来说,解析工具并没有找到 key 为 version 的参数,所以第一次命令的 rnPackage
的值应该是空的,输入正确后就是 0.47.2 了。 然后看 installCommand
这个变量,就是最终执行的命令。其中一个参数是需要到 getInstallPackage(rnPackage)
去确定一下是什么。
function getInstallPackage(rnPackage) { var packageToInstall = 'react-native'; var isValidSemver = semver.valid(rnPackage); if (isValidSemver) { packageToInstall += '@' + isValidSemver; } else if (rnPackage) { // for tar.gz or alternative paths packageToInstall = rnPackage; } return packageToInstall; } 复制代码
OMG! 看到上面的代码 激不激动,终于真相大白了!! 按照我的第一次错误的写法,这个 rnPackage 是空,然后
var isValidSemver = semver.valid(rnPackage); 复制代码
这一行代码的含义是进行一个版本语义化规范的检查,就是你创建的版本号必须符合semver语义化规范,也就是 x.y.z 的格式,比如 0.47.2 ,然而我现在传的空,肯定是不符合规范的,果断返回 false ,所以该方法会返回 "react-native", 默认会安装最新版。 而我后来正确的写法,是符合规范的,最终该方法会返回 "react-native@0.47.2" ! 然后就会下载指定的版本了。
最后我们这边可以验证下,输出的 log 参数是不是我们在代码中看到的。
上图:
果然如此~~
然后终于理解了,react-native 中文网 中提示如果创建指定版本, 版本号必须满足两位小数点 这句话是为什么了。
step3. 总结 & 填坑
所以说了那么多,如果想在 init 时候指定版本号,非常简单,,就是官网指出的:
react-native init MyApp --version 0.44.3
但必须注意检查两点(估计也就我这么粗心的人会犯吧):
1. --version
一定要加空格,千万不要写成 --version0.44.3
2.版本号一定要两位小数点,必须符合semver语义化规范
以上所述就是小编给大家介绍的《React Native --踩坑记 之 创建指定 React Native版本的项目》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Spring中Bean创建完成后执行指定代码的几种实现方式
- c# – “SMTP主机未指定” – 但是是否指定?
- 运维安全 | 如何限制指定账户不能SSH只能SFTP在指定目录
- Zabbix监控指定端口
- Android指定专用APN
- iOS 指定初始化方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RESTful Web Services Cookbook中文版
Subbu Allamaraju / 丁雪丰、常可 / 电子工业出版社 / 2011-9 / 59.00元
RESTful Web Services Cookbook中文版:REST最佳实践手册,ISBN:9787121143908,作者:(美)Subbu Allamaraju(沙布·阿拉马拉尤)著,丁雪丰,常可 译一起来看看 《RESTful Web Services Cookbook中文版》 这本书的介绍吧!
MD5 加密
MD5 加密工具
RGB HSV 转换
RGB HSV 互转工具