2021-06-13 18:04:48 +00:00
"use strict" ;
2020-03-29 10:04:49 +00:00
// Do this as the first thing so that any code reading it knows the right env.
2021-06-13 18:04:48 +00:00
process . env . BABEL _ENV = "production" ;
process . env . NODE _ENV = "production" ;
// If we want BAPS, specify it as the first command line argument.
var args = process . argv . slice ( 2 ) ; // Remove node start.js
if ( args . length > 0 && args [ 0 ] === "baps" ) {
process . env . NODE _ENV = "baps" ;
}
2020-03-29 10:04:49 +00:00
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
2021-06-13 18:04:48 +00:00
process . on ( "unhandledRejection" , ( err ) => {
2020-03-29 10:04:49 +00:00
throw err ;
} ) ;
// Ensure environment variables are read.
2021-06-13 18:04:48 +00:00
require ( "../config/env" ) ;
const path = require ( "path" ) ;
const chalk = require ( "react-dev-utils/chalk" ) ;
const fs = require ( "fs-extra" ) ;
const webpack = require ( "webpack" ) ;
const configFactory = require ( "../config/webpack.config" ) ;
const paths = require ( "../config/paths" ) ;
const checkRequiredFiles = require ( "react-dev-utils/checkRequiredFiles" ) ;
const formatWebpackMessages = require ( "react-dev-utils/formatWebpackMessages" ) ;
const printHostingInstructions = require ( "react-dev-utils/printHostingInstructions" ) ;
const FileSizeReporter = require ( "react-dev-utils/FileSizeReporter" ) ;
const printBuildError = require ( "react-dev-utils/printBuildError" ) ;
2020-03-29 10:04:49 +00:00
const measureFileSizesBeforeBuild =
FileSizeReporter . measureFileSizesBeforeBuild ;
const printFileSizesAfterBuild = FileSizeReporter . printFileSizesAfterBuild ;
const useYarn = fs . existsSync ( paths . yarnLockFile ) ;
// These sizes are pretty large. We'll warn for bundles exceeding them.
const WARN _AFTER _BUNDLE _GZIP _SIZE = 512 * 1024 ;
const WARN _AFTER _CHUNK _GZIP _SIZE = 1024 * 1024 ;
const isInteractive = process . stdout . isTTY ;
// Warn and crash if required files are missing
if ( ! checkRequiredFiles ( [ paths . appHtml , paths . appIndexJs ] ) ) {
process . exit ( 1 ) ;
}
// Generate configuration
2021-06-13 18:04:48 +00:00
const config = configFactory ( "production" ) ;
2020-03-29 10:04:49 +00:00
// We require that you explicitly set browsers and do not fall back to
// browserslist defaults.
2021-06-13 18:04:48 +00:00
const { checkBrowsers } = require ( "react-dev-utils/browsersHelper" ) ;
2020-03-29 10:04:49 +00:00
checkBrowsers ( paths . appPath , isInteractive )
. then ( ( ) => {
// First, read the current file sizes in build directory.
// This lets us display how much they changed later.
return measureFileSizesBeforeBuild ( paths . appBuild ) ;
} )
2021-06-13 18:04:48 +00:00
. then ( ( previousFileSizes ) => {
2020-03-29 10:04:49 +00:00
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
fs . emptyDirSync ( paths . appBuild ) ;
// Merge with the public folder
copyPublicFolder ( ) ;
// Start the webpack build
return build ( previousFileSizes ) ;
} )
. then (
( { stats , previousFileSizes , warnings } ) => {
if ( warnings . length ) {
2021-06-13 18:04:48 +00:00
console . log ( chalk . yellow ( "Compiled with warnings.\n" ) ) ;
console . log ( warnings . join ( "\n\n" ) ) ;
2020-03-29 10:04:49 +00:00
console . log (
2021-06-13 18:04:48 +00:00
"\nSearch for the " +
chalk . underline ( chalk . yellow ( "keywords" ) ) +
" to learn more about each warning."
2020-03-29 10:04:49 +00:00
) ;
console . log (
2021-06-13 18:04:48 +00:00
"To ignore, add " +
chalk . cyan ( "// eslint-disable-next-line" ) +
" to the line before.\n"
2020-03-29 10:04:49 +00:00
) ;
} else {
2021-06-13 18:04:48 +00:00
console . log ( chalk . green ( "Compiled successfully.\n" ) ) ;
2020-03-29 10:04:49 +00:00
}
2021-06-13 18:04:48 +00:00
console . log ( "File sizes after gzip:\n" ) ;
2020-03-29 10:04:49 +00:00
printFileSizesAfterBuild (
stats ,
previousFileSizes ,
paths . appBuild ,
WARN _AFTER _BUNDLE _GZIP _SIZE ,
WARN _AFTER _CHUNK _GZIP _SIZE
) ;
console . log ( ) ;
const appPackage = require ( paths . appPackageJson ) ;
const publicUrl = paths . publicUrl ;
const publicPath = config . output . publicPath ;
const buildFolder = path . relative ( process . cwd ( ) , paths . appBuild ) ;
printHostingInstructions (
appPackage ,
publicUrl ,
publicPath ,
buildFolder ,
useYarn
) ;
} ,
2021-06-13 18:04:48 +00:00
( err ) => {
const tscCompileOnError = process . env . TSC _COMPILE _ON _ERROR === "true" ;
2020-03-29 10:04:49 +00:00
if ( tscCompileOnError ) {
2021-06-13 18:04:48 +00:00
console . log (
chalk . yellow (
"Compiled with the following type errors (you may want to check these before deploying your app):\n"
)
) ;
2020-03-29 10:04:49 +00:00
printBuildError ( err ) ;
} else {
2021-06-13 18:04:48 +00:00
console . log ( chalk . red ( "Failed to compile.\n" ) ) ;
2020-03-29 10:04:49 +00:00
printBuildError ( err ) ;
process . exit ( 1 ) ;
}
}
)
2021-06-13 18:04:48 +00:00
. catch ( ( err ) => {
2020-03-29 10:04:49 +00:00
if ( err && err . message ) {
console . log ( err . message ) ;
}
process . exit ( 1 ) ;
} ) ;
// Create the production build and print the deployment instructions.
function build ( previousFileSizes ) {
// We used to support resolving modules according to `NODE_PATH`.
// This now has been deprecated in favor of jsconfig/tsconfig.json
// This lets you use absolute paths in imports inside large monorepos:
if ( process . env . NODE _PATH ) {
console . log (
chalk . yellow (
2021-06-13 18:04:48 +00:00
"Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app."
2020-03-29 10:04:49 +00:00
)
) ;
console . log ( ) ;
}
2021-06-13 18:04:48 +00:00
console . log ( "Creating an optimized production build..." ) ;
2020-03-29 10:04:49 +00:00
const compiler = webpack ( config ) ;
return new Promise ( ( resolve , reject ) => {
compiler . run ( ( err , stats ) => {
let messages ;
if ( err ) {
if ( ! err . message ) {
return reject ( err ) ;
}
messages = formatWebpackMessages ( {
errors : [ err . message ] ,
warnings : [ ] ,
} ) ;
} else {
messages = formatWebpackMessages (
stats . toJson ( { all : false , warnings : true , errors : true } )
) ;
}
if ( messages . errors . length ) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if ( messages . errors . length > 1 ) {
messages . errors . length = 1 ;
}
2021-06-13 18:04:48 +00:00
return reject ( new Error ( messages . errors . join ( "\n\n" ) ) ) ;
2020-03-29 10:04:49 +00:00
}
if (
process . env . CI &&
2021-06-13 18:04:48 +00:00
( typeof process . env . CI !== "string" ||
process . env . CI . toLowerCase ( ) !== "false" ) &&
2020-03-29 10:04:49 +00:00
messages . warnings . length
) {
console . log (
chalk . yellow (
2021-06-13 18:04:48 +00:00
"\nTreating warnings as errors because process.env.CI = true.\n" +
"Most CI servers set it automatically.\n"
2020-03-29 10:04:49 +00:00
)
) ;
2021-06-13 18:04:48 +00:00
return reject ( new Error ( messages . warnings . join ( "\n\n" ) ) ) ;
2020-03-29 10:04:49 +00:00
}
return resolve ( {
stats ,
previousFileSizes ,
warnings : messages . warnings ,
} ) ;
} ) ;
} ) ;
}
function copyPublicFolder ( ) {
fs . copySync ( paths . appPublic , paths . appBuild , {
dereference : true ,
2021-06-13 18:04:48 +00:00
filter : ( file ) => file !== paths . appHtml ,
2020-03-29 10:04:49 +00:00
} ) ;
}