eject.js 4.01 KiB
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
var createJestConfig = require('../utils/createJestConfig');
var fs = require('fs');
var path = require('path');
var prompt = require('react-dev-utils/prompt');
var rimrafSync = require('rimraf').sync;
var spawnSync = require('cross-spawn').sync;
prompt(
  'Are you sure you want to eject? This action is permanent.',
  false
).then(shouldEject => {
  if (!shouldEject) {
    console.log('Close one! Eject aborted.');
    process.exit(1);
  console.log('Ejecting...');
  console.log();
  var ownPath = path.join(__dirname, '..');
  var appPath = path.join(ownPath, '..', '..');
  var files = [
    '.babelrc',
    '.eslintrc',
    path.join('config', 'env.js'),
    path.join('config', 'paths.js'),
    path.join('config', 'polyfills.js'),
    path.join('config', 'webpack.config.dev.js'),
    path.join('config', 'webpack.config.prod.js'),
    path.join('config', 'jest', 'CSSStub.js'),
    path.join('config', 'jest', 'FileStub.js'),
    path.join('scripts', 'build.js'),
    path.join('scripts', 'start.js'),
    path.join('scripts', 'test.js')
  // Ensure that the app folder is clean and we won't override any files
  files.forEach(function(file) {
    if (fs.existsSync(path.join(appPath, file))) {
      console.error(
        '`' + file + '` already exists in your app folder. We cannot ' +
        'continue as you would lose all the changes in that file or directory. ' +
        'Please delete it (maybe make a copy for backup) and run this ' +
        'command again.'
      process.exit(1);
  });
  // Copy the files over
  fs.mkdirSync(path.join(appPath, 'config'));
  fs.mkdirSync(path.join(appPath, 'config', 'jest'));
  fs.mkdirSync(path.join(appPath, 'scripts'));
  files.forEach(function(file) {
    console.log('Copying ' + file + ' to ' + appPath);
    var content = fs
      .readFileSync(path.join(ownPath, file), 'utf8')
      // Remove dead code from .js files on eject
      .replace(/\/\/ @remove-on-eject-begin([\s\S]*?)\/\/ @remove-on-eject-end/mg, '')
      // Remove dead code from .applescript files on eject
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
.replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '') .trim() + '\n'; fs.writeFileSync(path.join(appPath, file), content); }); console.log(); var ownPackage = require(path.join(ownPath, 'package.json')); var appPackage = require(path.join(appPath, 'package.json')); var ownPackageName = ownPackage.name; console.log('Removing dependency: ' + ownPackageName); delete appPackage.devDependencies[ownPackageName]; Object.keys(ownPackage.dependencies).forEach(function (key) { // For some reason optionalDependencies end up in dependencies after install if (ownPackage.optionalDependencies[key]) { return; } console.log('Adding dependency: ' + key); appPackage.devDependencies[key] = ownPackage.dependencies[key]; }); console.log('Updating scripts'); delete appPackage.scripts['eject']; Object.keys(appPackage.scripts).forEach(function (key) { appPackage.scripts[key] = appPackage.scripts[key] .replace( new RegExp(ownPackageName + ' (\w+)', 'g'), 'node scripts/$1.js' ); }); // Add Jest config appPackage.jest = createJestConfig( filePath => path.join('<rootDir>', filePath), null, true ); console.log('Writing package.json'); fs.writeFileSync( path.join(appPath, 'package.json'), JSON.stringify(appPackage, null, 2) ); console.log(); console.log('Running npm install...'); rimrafSync(ownPath); spawnSync('npm', ['install'], {stdio: 'inherit'}); console.log('Ejected successfully!'); console.log(); console.log('Please consider sharing why you ejected in this survey:'); console.log(' http://goo.gl/forms/Bi6CZjk1EqsdelXk1'); console.log(); });