diff --git a/config/babel.dev.js b/config/babel.dev.js index 89096734713..60e3f7f2b36 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end module.exports = { // Don't try to find .babelrc because we want to force this configuration. diff --git a/config/babel.prod.js b/config/babel.prod.js index 92491bfcacb..1e4690a0915 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end module.exports = { // Don't try to find .babelrc because we want to force this configuration. diff --git a/config/env.js b/config/env.js index cfa10c75b44..66acf119b84 100644 --- a/config/env.js +++ b/config/env.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be // injected into the application via DefinePlugin in Webpack configuration. diff --git a/config/eslint.js b/config/eslint.js index 761add0f718..082bd8048a2 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end // Inspired by https://github.com/airbnb/javascript but less opinionated. diff --git a/config/jest/CSSStub.js b/config/jest/CSSStub.js index 05fb9d0d70f..05810269ac6 100644 --- a/config/jest/CSSStub.js +++ b/config/jest/CSSStub.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * @@ -7,5 +8,6 @@ * * @flow */ +// @remove-on-eject-end module.exports = {}; diff --git a/config/jest/FileStub.js b/config/jest/FileStub.js index 96d28629fe6..c95c3e790a1 100644 --- a/config/jest/FileStub.js +++ b/config/jest/FileStub.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * @@ -7,5 +8,6 @@ * * @flow */ +// @remove-on-eject-end module.exports = "test-file-stub"; diff --git a/config/jest/transform.js b/config/jest/transform.js index 9f51b1a8558..3a085e93e65 100644 --- a/config/jest/transform.js +++ b/config/jest/transform.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * @@ -5,6 +6,7 @@ * 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. */ +// @remove-on-eject-end const babelDev = require('../babel.dev'); const babelJest = require('babel-jest'); diff --git a/config/paths.js b/config/paths.js index e6f2ff6cb3a..e85fe385a6e 100644 --- a/config/paths.js +++ b/config/paths.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,60 +7,47 @@ * 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. */ - -// TODO: we can split this file into several files (pre-eject, post-eject, test) -// and use those instead. This way we don't need to branch here. +// @remove-on-eject-end var path = require('path'); -// True after ejecting, false when used as a dependency -var isEjected = ( - path.resolve(path.join(__dirname, '..')) === - path.resolve(process.cwd()) -); +function resolveApp(relativePath) { + return path.resolve(relativePath); +} -// Are we developing create-react-app locally? -var isInCreateReactAppSource = ( - process.argv.some(arg => arg.indexOf('--debug-template') > -1) -); +// config after eject: we're in ./config/ +module.exports = { + appBuild: resolveApp('build'), + appHtml: resolveApp('index.html'), + appPackageJson: resolveApp('package.json'), + appSrc: resolveApp('src'), + appNodeModules: resolveApp('node_modules'), + ownNodeModules: resolveApp('node_modules') +}; +// @remove-on-eject-begin function resolveOwn(relativePath) { return path.resolve(__dirname, relativePath); } +// config before eject: we're in ./node_modules/react-scripts/config/ +module.exports = { + appBuild: resolveApp('build'), + appHtml: resolveApp('index.html'), + appPackageJson: resolveApp('package.json'), + appSrc: resolveApp('src'), + appNodeModules: resolveApp('node_modules'), + // this is empty with npm3 but node resolution searches higher anyway: + ownNodeModules: resolveOwn('../node_modules') +}; +// @remove-on-eject-end -function resolveApp(relativePath) { - return path.resolve(relativePath); -} - -if (isInCreateReactAppSource) { - // create-react-app development: we're in ./config/ - module.exports = { - appBuild: resolveOwn('../build'), - appHtml: resolveOwn('../template/index.html'), - appPackageJson: resolveOwn('../package.json'), - appSrc: resolveOwn('../template/src'), - appNodeModules: resolveOwn('../node_modules'), - ownNodeModules: resolveOwn('../node_modules') - }; -} else if (!isEjected) { - // before eject: we're in ./node_modules/react-scripts/config/ - module.exports = { - appBuild: resolveApp('build'), - appHtml: resolveApp('index.html'), - appPackageJson: resolveApp('package.json'), - appSrc: resolveApp('src'), - appNodeModules: resolveApp('node_modules'), - // this is empty with npm3 but node resolution searches higher anyway: - ownNodeModules: resolveOwn('../node_modules') - }; -} else { - // after eject: we're in ./config/ - module.exports = { - appBuild: resolveApp('build'), - appHtml: resolveApp('index.html'), - appPackageJson: resolveApp('package.json'), - appSrc: resolveApp('src'), - appNodeModules: resolveApp('node_modules'), - ownNodeModules: resolveApp('node_modules') - }; -} +// @remove-on-publish-begin +module.exports = { + appBuild: resolveOwn('../build'), + appHtml: resolveOwn('../template/index.html'), + appPackageJson: resolveOwn('../package.json'), + appSrc: resolveOwn('../template/src'), + appNodeModules: resolveOwn('../node_modules'), + ownNodeModules: resolveOwn('../node_modules') +}; +// @remove-on-publish-end diff --git a/config/polyfills.js b/config/polyfills.js index 7e601502b24..a1353ca3d2d 100644 --- a/config/polyfills.js +++ b/config/polyfills.js @@ -1,3 +1,14 @@ +// @remove-on-eject-begin +/** + * 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. + */ +// @remove-on-eject-end + if (typeof Promise === 'undefined') { // Rejection tracking prevents a common issue where React gets into an // inconsistent state due to an error, but it gets swallowed by a Promise, diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 2b6da367f79..94a9b69a45a 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end var path = require('path'); var autoprefixer = require('autoprefixer'); diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 5781ae8636b..8d6a27cfda6 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end var path = require('path'); var autoprefixer = require('autoprefixer'); diff --git a/global-cli/index.js b/global-cli/index.js index e8dc5a7184a..63c484a7d9e 100644 --- a/global-cli/index.js +++ b/global-cli/index.js @@ -51,7 +51,7 @@ var pathExists = require('path-exists'); * Example of valid values: * - a specific npm version: "0.22.0-rc1" * - a .tgz archive from any npm repo: "https://registry.npmjs.org/react-scripts/-/react-scripts-0.20.0.tgz" - * - a package prepared with `npm pack`: "/Users/home/vjeux/create-react-app/react-scripts-0.22.0.tgz" + * - a package prepared with `tasks/clean_pack.sh`: "/Users/home/vjeux/create-react-app/react-scripts-0.22.0.tgz" */ var commands = argv._; if (commands.length === 0) { diff --git a/package.json b/package.json index 1b389da8005..3ab9b656780 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "build": "node scripts/build.js --debug-template", - "create-react-app": "node global-cli/index.js --scripts-version \"$PWD/`npm pack`\"", + "create-react-app": "node global-cli/index.js --scripts-version \"$PWD/`tasks/clean_pack.sh`\"", "e2e": "tasks/e2e.sh", "start": "node scripts/start.js --debug-template", "test": "node scripts/test.js --debug-template" diff --git a/scripts/build.js b/scripts/build.js index b02d8dc3200..e60b554466f 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end // Do this as the first thing so that any code reading it knows the right env. process.env.NODE_ENV = 'production'; diff --git a/scripts/eject.js b/scripts/eject.js index 55661d19285..67d48aba814 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -74,10 +74,10 @@ prompt( console.log('Copying ' + file + ' to ' + appPath); var content = fs .readFileSync(path.join(ownPath, file), 'utf8') - // Remove license header from JS - .replace(/^\/\*\*(\*(?!\/)|[^*])*\*\//, '') - // Remove license header from AppleScript - .replace(/^--.*\n/gm, '') + // 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 + .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '') .trim() + '\n'; fs.writeFileSync(path.join(appPath, file), content); }); diff --git a/scripts/start.js b/scripts/start.js index aa68ab40ff3..09e3a7f9248 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end process.env.NODE_ENV = 'development'; diff --git a/scripts/utils/WatchMissingNodeModulesPlugin.js b/scripts/utils/WatchMissingNodeModulesPlugin.js index ee99c218806..45c3616d2e1 100644 --- a/scripts/utils/WatchMissingNodeModulesPlugin.js +++ b/scripts/utils/WatchMissingNodeModulesPlugin.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end // This Webpack plugin ensures `npm install ` forces a project rebuild. // We’re not sure why this isn't Webpack's default behavior. diff --git a/scripts/utils/chrome.applescript b/scripts/utils/chrome.applescript index 0035dcad5e6..07d229652d8 100644 --- a/scripts/utils/chrome.applescript +++ b/scripts/utils/chrome.applescript @@ -1,9 +1,14 @@ --- Copyright (c) 2015-present, Facebook, Inc. --- All rights reserved. --- --- This source code is licensed under the BSD-style license found in the +-- @remove-on-eject-begin +(* +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. +of patent rights can be found in the PATENTS file in the same directory. +*) +-- @remove-on-eject-end + on run argv set theURL to item 1 of argv diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index a420e6fd6bc..139c7813c33 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end module.exports = (resolve, rootDir) => { const config = { diff --git a/scripts/utils/prompt.js b/scripts/utils/prompt.js index b1a806b676b..ed32c750612 100644 --- a/scripts/utils/prompt.js +++ b/scripts/utils/prompt.js @@ -1,3 +1,4 @@ +// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -6,6 +7,7 @@ * 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. */ +// @remove-on-eject-end var rl = require('readline'); diff --git a/tasks/clean_pack.sh b/tasks/clean_pack.sh new file mode 100755 index 00000000000..b7d9bf7fac9 --- /dev/null +++ b/tasks/clean_pack.sh @@ -0,0 +1,78 @@ +# 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. + +# In success case, the only output to stdout is the packagename, +# which might be used by the caller of `tasks/clean_pack.sh` + +# Start even if run from root directory +cd "$(dirname "$0")" + +# print error messages to stderr +# the cleanup function is optionally defined in caller script +function handle_error { + echo "$(basename $0): \033[31mERROR!\033[m An error was encountered executing \033[36mline $1\033[m." 1>&2; + cleanup + echo 'Exiting with error.' 1>&2; + exit 1 +} + +function handle_exit { + cleanup + echo 'Exiting without error.' 1>&2; + exit +} + +function cleanup { + cd $initial_path + # remove Jest snap test file from local dev project if exists + rm ../template/src/__tests__/__snapshots__/App-test.js.snap + rm -rf ../$clean_path +} + +# Exit the script with a helpful error message when any error is encountered +trap 'set +x; handle_error $LINENO $BASH_COMMAND' ERR + +# Cleanup before exit on any termination signal +trap 'set +x; handle_exit' SIGQUIT SIGTERM SIGINT SIGKILL SIGHUP + +# `tasks/clean_pack.sh` the two directories to make sure they are valid npm modules +initial_path=$PWD + +# Go to root +cd .. +# create a temporary clean folder that contains production only code +# do not overwrite any files in the current folder +clean_path=`mktemp -d clean_XXXX` + +# copy files to folder .clean-pack +# `npm publish` looks package.json, if it has a files field, only pack listed files +# follwoing folders, although not listed in the files field, are not copied +# - .git : contains lot of small files +# - $clean_path : the destination folder +# - node_modules : contains lots of small files +# - build : .gitignored folder used in local development +rsync -av --exclude='.git' --exclude=$clean_path\ + --exclude='node_modules' --exclude='build'\ + './' $clean_path >/dev/null + +cd $clean_path + +# remove dev-only code +files="$(find -L . -name "*.js" -type f)" +for file in $files; do + sed -i.bak '/\/\/ @remove-on-publish-begin/,/\/\/ @remove-on-publish-end/d' $file + rm $file.bak +done + +# Pack! +packname=`npm pack` + +# copy package to current folder +cd .. +cp -f $clean_path/$packname ./ +cleanup +echo $packname diff --git a/tasks/e2e.sh b/tasks/e2e.sh index 6e6c20c9420..38260102c7b 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -16,16 +16,17 @@ function cleanup { rm -rf $temp_cli_path $temp_app_path } +# error messages are redirected to stderr function handle_error { - echo "$(basename $0): \033[31mERROR!\033[m An error was encountered executing \033[36mline $1\033[m." + echo "$(basename $0): \033[31mERROR!\033[m An error was encountered executing \033[36mline $1\033[m." 1>&2; cleanup - echo 'Exiting with error.' + echo 'Exiting with error.' 1>&2; exit 1 } function handle_exit { cleanup - echo 'Exiting without error.' + echo 'Exiting without error.' 1>&2; exit } @@ -38,7 +39,7 @@ trap 'set +x; handle_exit' SIGQUIT SIGTERM SIGINT SIGKILL SIGHUP # Echo every command being executed set -x -# npm pack the two directories to make sure they are valid npm modules +# `tasks/clean_pack.sh` the two directories to make sure they are valid npm modules initial_path=$PWD cd .. @@ -51,7 +52,7 @@ perl -i -p0e 's/bundledDependencies.*?]/bundledDependencies": []/s' package.json # Pack react-scripts npm install -scripts_path=$PWD/`npm pack` +scripts_path=$PWD/`tasks/clean_pack.sh` # lint ./node_modules/.bin/eslint --ignore-path .gitignore ./ diff --git a/tasks/release.sh b/tasks/release.sh index c52d7c40bef..f95b65bd407 100755 --- a/tasks/release.sh +++ b/tasks/release.sh @@ -31,6 +31,30 @@ if [ -n "$(git status --porcelain)" ]; then exit 1; fi +# create a temporary clean folder that contains production only code +# do not overwrite any files in the current folder +clean_path=`mktemp -d clean_XXXX` + +# copy files to folder .clean-pack +# `npm publish` looks package.json, if it has a files field, only pack listed files +# follwoing folders, although not listed in the files field, are not copied +# - .git : contains lot of small files +# - $clean_path : the destination folder +# - node_modules : contains lots of small files +# - build : .gitignored folder used in local development +rsync -av --exclude='.git' --exclude=$clean_path\ + --exclude='node_modules' --exclude='build'\ + './' '$clean_path' >/dev/null + +cd $clean_path + +# remove dev-only code +files="$(find -L . -name "*.js" -type f)" +for file in $files; do + sed -i.bak '/\/\/ @remove-on-publish-begin/,/\/\/ @remove-on-publish-end/d' $file + rm $file.bak +done + # Update deps rm -rf node_modules rm -rf ~/.npm @@ -44,12 +68,12 @@ npm dedupe # Since it's in optionalDependencies, it will attempt install outside bundle rm -rf node_modules/fsevents -# This modifies package.json to copy all dependencies to bundledDependencies -# We will revert package.json back after release to avoid doing it every time +# This modifies $clean_path/package.json to copy all dependencies to bundledDependencies node ./node_modules/.bin/bundle-deps # Go! npm publish "$@" -# Discard changes to package.json -git checkout -- . +# cleanup +cd .. +rm -rf $clean_path