2018-04-21 04:34:02 +08:00
'use strict' ;
// Do this as the first thing so that any code reading it knows the right env.
process . env . BABEL _ENV = 'development' ;
process . env . NODE _ENV = 'development' ;
// 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.
process . on ( 'unhandledRejection' , err => {
throw err ;
} ) ;
// Ensure environment variables are read.
require ( '../config/env' ) ;
2018-11-10 00:06:46 +08:00
2018-04-21 04:34:02 +08:00
const fs = require ( 'fs' ) ;
2019-04-28 10:19:34 +08:00
const chalk = require ( 'react-dev-utils/chalk' ) ;
2018-04-21 04:34:02 +08:00
const webpack = require ( 'webpack' ) ;
const WebpackDevServer = require ( 'webpack-dev-server' ) ;
const clearConsole = require ( 'react-dev-utils/clearConsole' ) ;
const checkRequiredFiles = require ( 'react-dev-utils/checkRequiredFiles' ) ;
const {
choosePort ,
createCompiler ,
prepareProxy ,
prepareUrls ,
} = require ( 'react-dev-utils/WebpackDevServerUtils' ) ;
const openBrowser = require ( 'react-dev-utils/openBrowser' ) ;
const paths = require ( '../config/paths' ) ;
2019-04-28 10:19:34 +08:00
const configFactory = require ( '../config/webpack.config' ) ;
2018-04-21 04:34:02 +08:00
const createDevServerConfig = require ( '../config/webpackDevServer.config' ) ;
const useYarn = fs . existsSync ( paths . yarnLockFile ) ;
const isInteractive = process . stdout . isTTY ;
// Warn and crash if required files are missing
2018-11-10 00:06:46 +08:00
if ( ! checkRequiredFiles ( [ paths . appHtml , paths . appDemoIndexJs ] ) ) {
2018-04-21 04:34:02 +08:00
process . exit ( 1 ) ;
}
// Tools like Cloud9 rely on this.
const DEFAULT _PORT = parseInt ( process . env . PORT , 10 ) || 3000 ;
const HOST = process . env . HOST || '0.0.0.0' ;
2018-11-10 00:06:46 +08:00
if ( process . env . HOST ) {
console . log (
chalk . cyan (
` Attempting to bind to HOST environment variable: ${ chalk . yellow (
chalk . bold ( process . env . HOST )
) } `
)
) ;
console . log (
` If this was unintentional, check that you haven't mistakenly set it in your shell. `
) ;
console . log (
2019-04-28 10:19:34 +08:00
` Learn more here: ${ chalk . yellow ( 'https://bit.ly/CRA-advanced-config' ) } `
2018-11-10 00:06:46 +08:00
) ;
console . log ( ) ;
}
2019-04-28 10:19:34 +08:00
// We require that you explicitly set browsers and do not fall back to
2018-11-10 00:06:46 +08:00
// browserslist defaults.
const { checkBrowsers } = require ( 'react-dev-utils/browsersHelper' ) ;
checkBrowsers ( paths . appPath , isInteractive )
. then ( ( ) => {
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
return choosePort ( HOST , DEFAULT _PORT ) ;
} )
2018-04-21 04:34:02 +08:00
. then ( port => {
if ( port == null ) {
// We have not found a port.
return ;
}
2019-03-11 03:58:22 +08:00
const args = process . argv ;
const testMode = args [ 2 ] === "--testMode" ;
2019-04-28 10:19:34 +08:00
const config = configFactory ( 'development' ) ;
2018-04-21 04:34:02 +08:00
const protocol = process . env . HTTPS === 'true' ? 'https' : 'http' ;
const appName = require ( paths . appPackageJson ) . name ;
2019-04-28 10:19:34 +08:00
const useTypeScript = fs . existsSync ( paths . appTsConfig ) ;
2018-04-21 04:34:02 +08:00
const urls = prepareUrls ( protocol , HOST , port ) ;
2019-04-28 10:19:34 +08:00
const devSocket = {
warnings : warnings =>
devServer . sockWrite ( devServer . sockets , 'warnings' , warnings ) ,
errors : errors =>
devServer . sockWrite ( devServer . sockets , 'errors' , errors ) ,
} ;
2018-04-21 04:34:02 +08:00
// Create a webpack compiler that is configured with custom messages.
2019-04-28 10:19:34 +08:00
const compiler = createCompiler ( {
appName ,
config ,
devSocket ,
urls ,
useYarn ,
useTypeScript ,
webpack ,
} ) ;
2018-04-21 04:34:02 +08:00
// Load proxy config
const proxySetting = require ( paths . appPackageJson ) . proxy ;
const proxyConfig = prepareProxy ( proxySetting , paths . appPublic ) ;
2018-11-10 00:06:46 +08:00
// Serve webpack assets generated by the compiler over a web server.
2018-04-21 04:34:02 +08:00
const serverConfig = createDevServerConfig (
proxyConfig ,
urls . lanUrlForConfig
) ;
const devServer = new WebpackDevServer ( compiler , serverConfig ) ;
// Launch WebpackDevServer.
devServer . listen ( port , HOST , err => {
if ( err ) {
return console . log ( err ) ;
}
if ( isInteractive ) {
clearConsole ( ) ;
}
2019-04-28 10:19:34 +08:00
// 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 (
'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.'
)
) ;
console . log ( ) ;
}
2018-04-21 04:34:02 +08:00
console . log ( chalk . cyan ( 'Starting the development server...\n' ) ) ;
openBrowser ( urls . localUrlForBrowser ) ;
2019-03-11 03:58:22 +08:00
/ * *
* Handle testMode
* /
if ( testMode ) {
2019-03-17 10:38:50 +08:00
compiler . hooks . done . tap ( 'done' , ( stats ) => {
2019-03-11 03:58:22 +08:00
stats = stats . toJson ( ) ;
if ( stats . errors && stats . errors . length > 0 ) {
return ;
}
console . warn ( "App started in test mode. Closing in 5 seconds." ) ;
let closeTimeout = setTimeout ( ( ) => {
clearTimeout ( closeTimeout ) ;
devServer . close ( ) ;
process . exit ( ) ;
} , 5000 ) ;
} ) ;
}
2018-04-21 04:34:02 +08:00
} ) ;
[ 'SIGINT' , 'SIGTERM' ] . forEach ( function ( sig ) {
process . on ( sig , function ( ) {
devServer . close ( ) ;
process . exit ( ) ;
} ) ;
} ) ;
} )
. catch ( err => {
if ( err && err . message ) {
console . log ( err . message ) ;
}
process . exit ( 1 ) ;
2019-04-28 10:19:34 +08:00
} ) ;