Before the speech
Recently, I have been writing RN projects, during which I encountered a lot of holes, and then I wanted to record the process of filling holes (if you want to see the answers, you can ignore my heart and skip to the end of the summary).
Step1. I secretly dug a hole for myself?
As a result, the first step was to create a new demo and input react Native init yx_rnDemo in terminal quickly. After a long wait, the project was successfully established. Then use the IDE to open the demo and execute the react-native run-Android command. A closer look at the error log shows that various Android dependencies failed to download. Then I check the react-native version of package.json and find that the latest version is referenced. Then I click the Android folder and find that the quoted Gradle version is 3.1.4, but I still use the 2.3.3 version.
Because I am lazy (this sentence appears in my blog many times, lazy is the root of all evil, sin ~~), do not want to upgrade, and then configure a series of things, so according to the Chinese website to create a specified version of the method:
Tip: You can use the –version argument (note the two bars) to create a project of the specified version. Example: React-native init MyApp –version 0.44.3. Note that the version number must be accurate to two decimal points
React Native init yx_rnDemo –version0.47.2 (Inner OS, what?? In fact, careful friends may have found the problem, ha ha, SHH ~~)
Then I started all kinds of search engines, and found that everyone is created in this way, and the command given by RN official website is also like this, why others have no problem, I have a problem.
React-native init yx_rnDemo –verbose –version 0.47.2 react-native init yx_rnDemo –verbose –version 0.47.2 Is 0.47.2.
If you add a –verbose condition, you can create it successfully. Verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose verbose Verbose init yx_rnDemo –version 0.47.2 react-native init yx_rnDemo –version 0.47.2 react-native init yx_rnDemo –version 0.47.2
Scared me to turn over my first written command, a comparison, found my first command – Verison after no line break ~~
First: React native init yx_rnDemo –version0.47.2 Second: React -native init yx_rnDemo –version0.47.2
I could have ended there, but as a programmer who wants to have a soul, I’d like to know why the latest version was created without space, rather than the reason for the syntax error.
Step2. Step by step, analyze how the pit is generated
Index.js in the react-native cli folder is very important. Its only job is to initialize the repository and then forward all commands to the local react-Native version. So what we did when we initialized the project can be found in this file.
Open the JS file and start exploring. 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));
Copy the code
The first 62 lines of the file are used to declare variables and references. There are several variables that we need to know what they do:
The variable name | meaning |
---|---|
fs | File system manipulation module in Node.js |
path | Module of a gadget in Node.js that handles file paths |
exec | Node.js neutron process module, which generates a shell and runs commands on the shell |
execSync | Exec’s synchronization function, which blocks the Node.js event loop |
chalk | A plug-in that customizes the input style of console logs |
prompt | Node command line input control |
semver | Semver semantic version number |
options | Lightweight command line argument parsing tool |
One of the key variables options, the reference require(‘minimist’)(process.argv.slice(2)), is a command line parameter parsing tool. For example, the command line we enter is: React-native init yx_rnDemo –version 0.47.2 –version 0.47.2 is a resolveable key-value pair with key version and value 0.47.2.
In this file, the values of the key-value pairs we use can be seen in the comments of the screenshot:
-v
: Displays the dependencies between the current React native CLI version and React Nativeinit
: Create a new project and execute NPM install--verbose
:init
When added parameters, printinit
When the parameters of the- –
-template
: Specifies the name of the template to use --version
: Overrides the react-Native version installed by default (latest version). That is, if you want to create the specified version, you need to add this parameter
OK, the meaning of each variable is clear, let’s continue to explore ~~
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: //... The code is omittedbreak; }}Copy the code
The command variable is defined in line 116. The result of the command variable is the parsing parameter, which should be _ [‘init ‘, ‘yx_rnDEmo’], so it will go to the first option of switch, Execute init(Commands [1], options) with ‘yx_rnDemo ‘and options variables.
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); }}Copy the code
Very simple, first to determine whether the project name we choose conforms to the naming convention, and determine whether there is. So let’s go straight to the createProject(Name, options) method
4.
functioncreateProject(name, options) { //.... Code omits run(root, projectName, options); }Copy the code
This method creates the project folder and package.json file, and then runs (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) + '... '); / /... Code omitted installCommand ='npm install --save --save-exact ' + getInstallPackage(rnPackage);
if (options.verbose) {
installCommand += ' --verbose'; } / /... Code omission try {execSync(installCommand, {stdio: 'inherit'}); } catch (err) { //... } cli.init(root, projectName); }Copy the code
Where rnPackage is the parsed version parameter, so for my first use of the command: React-native init yx_rnDemo –version0.47.2: the react-native init yx_rnDemo — native init yx_rnDemo –version0.47.2 Then look at the installCommand variable, which is the final command executed. One of the arguments is that you need to go to getInstallPackage(rnPackage) to determine what it is.
function getInstallPackage(rnPackage) {
var packageToInstall = 'react-native';
var isValidSemver = semver.valid(rnPackage);
if (isValidSemver) {
packageToInstall += The '@' + isValidSemver;
} else if (rnPackage) {
// for tar.gz or alternative paths
packageToInstall = rnPackage;
}
return packageToInstall;
}
Copy the code
OMG!!! See the above code is not excited, finally the truth!! According to my first wrong writing, the rnPackage is empty, and then
var isValidSemver = semver.valid(rnPackage);
Copy the code
Semver (X.Y.Z, 0.47.2); semver (X.Y.Z, 0.47.2); semver (X.Y.Z, 0.47.2); So this method will return “React-native” and the latest version will be installed by default. When I write it correctly, it conforms to the specification and eventually returns “[email protected]”! The specified version will then be downloaded.
Finally, we can verify that the output log parameter is not what we see in the code.
Above:
Sure enough ~~
The react-Native Chinese version must contain two decimal points if a specified version is created.
Step3. Summary & pit filling
So with all that said, if you want to specify a version number for init, it’s very simple, as the official website says:
React-native init MyApp –version 0.44.3
But must pay attention to check two points (estimated also I so careless person will make it) :
1.--version
Always put a space, never write--version0.44.3
2. The version number must be matched with two decimal pointsSemver semantic specification
Refer to the article
Github.com/facebook/re… Nodejs. Cn/API/child_p… www.runoob.com/nodejs/node… Nodejs. Cn/API/fs. HTML… www.jianshu.com/p/231b931ab…