UNPKG

6.98 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 */
9
10'use strict';
11
12var fs = require('fs-extra');
13var path = require('path');
14var spawn = require('cross-spawn');
15var chalk = require('chalk');
16
17module.exports = function(appPath, appName, verbose, originalDirectory, template) {
18 var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name;
19 var ownPath = path.join(appPath, 'node_modules', ownPackageName);
20 var appPackage = require(path.join(appPath, 'package.json'));
21 var useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
22
23 // Copy over some of the devDependencies
24 appPackage.dependencies = appPackage.dependencies || {};
25 appPackage.devDependencies = appPackage.devDependencies || {};
26
27 // Setup the script rules
28 appPackage.scripts = {
29 'start': 'molmc-react-scripts start',
30 'build': 'molmc-react-scripts build',
31 'test': 'molmc-react-scripts test --env=jsdom',
32 'eject': 'molmc-react-scripts eject'
33 };
34
35 fs.writeFileSync(
36 path.join(appPath, 'package.json'),
37 JSON.stringify(appPackage, null, 2)
38 );
39
40 var readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
41 if (readmeExists) {
42 fs.renameSync(path.join(appPath, 'README.md'), path.join(appPath, 'README.old.md'));
43 }
44
45 // Copy the files for the user
46 var templatePath = template ? path.resolve(originalDirectory, template) : path.join(ownPath, 'template');
47 if (fs.existsSync(templatePath)) {
48 fs.copySync(templatePath, appPath);
49 } else {
50 console.error('Could not locate supplied template: ' + chalk.green(templatePath));
51 return;
52 }
53
54 // Rename gitignore after the fact to prevent npm from renaming it to .npmignore
55 // See: https://github.com/npm/npm/issues/1862
56 fs.move(path.join(appPath, 'gitignore'), path.join(appPath, '.gitignore'), [], function (err) {
57 if (err) {
58 // Append if there's already a `.gitignore` file there
59 if (err.code === 'EEXIST') {
60 var data = fs.readFileSync(path.join(appPath, 'gitignore'));
61 fs.appendFileSync(path.join(appPath, '.gitignore'), data);
62 fs.unlinkSync(path.join(appPath, 'gitignore'));
63 } else {
64 throw err;
65 }
66 }
67 });
68
69 // 添加eslintrc文件,使用ESLINT规范代码。
70 fs.copy(path.join(ownPath, 'eslintrc'), path.join(appPath, '.eslintrc'), [], function (err) {
71 if (err) {
72 if (err.code === 'EEXIST') {
73 var data = fs.readFileSync(path.join(ownPath, 'eslintrc'));
74 fs.appendFileSync(path.join(appPath, '.eslintrc'), data);
75 fs.unlinkSync(path.join(appPath, 'eslintrc'));
76 } else {
77 throw err;
78 }
79 }
80 });
81
82 // 添加eslintignore文件,过滤第三方库的代码规范检查。
83 fs.move(path.join(appPath, 'eslintignore'), path.join(appPath, '.eslintignore'), [], function (err) {
84 if (err) {
85 if (err.code === 'EEXIST') {
86 var data = fs.readFileSync(path.join(appPath, 'eslintignore'));
87 fs.appendFileSync(path.join(appPath, '.eslintignore'), data);
88 fs.unlinkSync(path.join(appPath, 'eslintignore'));
89 } else {
90 throw err;
91 }
92 }
93 });
94
95 // 添加editorconfig文件。
96 fs.move(path.join(appPath, 'editorconfig'), path.join(appPath, '.editorconfig'), [], function (err) {
97 if (err) {
98 if (err.code === 'EEXIST') {
99 var data = fs.readFileSync(path.join(appPath, 'editorconfig'));
100 fs.appendFileSync(path.join(appPath, '.editorconfig'), data);
101 fs.unlinkSync(path.join(appPath, 'editorconfig'));
102 } else {
103 throw err;
104 }
105 }
106 });
107
108 var command;
109 var args;
110
111 if (useYarn) {
112 command = 'yarnpkg';
113 args = ['add'];
114 } else {
115 command = 'npm';
116 args = [
117 'install',
118 '--save',
119 verbose && '--verbose'
120 ].filter(function(e) { return e; });
121 }
122 args.push('react', 'react-dom');
123
124 // Install additional template dependencies, if present
125 var templateDependenciesPath = path.join(appPath, '.template.dependencies.json');
126 if (fs.existsSync(templateDependenciesPath)) {
127 var templateDependencies = require(templateDependenciesPath).dependencies;
128 args = args.concat(Object.keys(templateDependencies).map(function (key) {
129 return key + '@' + templateDependencies[key];
130 }));
131 fs.unlinkSync(templateDependenciesPath);
132 }
133
134 // Install react and react-dom for backward compatibility with old CRA cli
135 // which doesn't install react and react-dom along with react-scripts
136 // or template is presetend (via --internal-testing-template)
137 if (!isReactInstalled(appPackage) || template) {
138 console.log('Installing react and react-dom using ' + command + '...');
139 console.log();
140
141 var proc = spawn.sync(command, args, {stdio: 'inherit'});
142 if (proc.status !== 0) {
143 console.error('`' + command + ' ' + args.join(' ') + '` failed');
144 return;
145 }
146 }
147
148 // Display the most elegant way to cd.
149 // This needs to handle an undefined originalDirectory for
150 // backward compatibility with old global-cli's.
151 var cdpath;
152 if (originalDirectory &&
153 path.join(originalDirectory, appName) === appPath) {
154 cdpath = appName;
155 } else {
156 cdpath = appPath;
157 }
158
159 // Change displayed command to yarn instead of yarnpkg
160 var displayedCommand = useYarn ? 'yarn' : 'npm';
161
162 console.log();
163 console.log('Success! Created ' + appName + ' at ' + appPath);
164 console.log('Inside that directory, you can run several commands:');
165 console.log();
166 console.log(chalk.cyan(' ' + displayedCommand + ' start'));
167 console.log(' Starts the development server.');
168 console.log();
169 console.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`));
170 console.log(' Bundles the app into static files for production.');
171 console.log();
172 console.log(chalk.cyan(' ' + displayedCommand + ' test'));
173 console.log(' Starts the test runner.');
174 console.log();
175 console.log(chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}eject`));
176 console.log(' Removes this tool and copies build dependencies, configuration files');
177 console.log(' and scripts into the app directory. If you do this, you can’t go back!');
178 console.log();
179 console.log('We suggest that you begin by typing:');
180 console.log();
181 console.log(chalk.cyan(' cd'), cdpath);
182 console.log(' ' + chalk.cyan(displayedCommand + ' start'));
183 if (readmeExists) {
184 console.log();
185 console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`'));
186 }
187 console.log();
188 console.log('Happy hacking!');
189};
190
191function isReactInstalled(appPackage) {
192 var dependencies = appPackage.dependencies || {};
193
194 return (
195 typeof dependencies.react !== 'undefined' &&
196 typeof dependencies['react-dom'] !== 'undefined'
197 )
198}