Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Meta
create-react-app
Commits
c1a984d9
Commit
c1a984d9
authored
8 years ago
by
Dan Abramov
Committed by
GitHub
8 years ago
Browse files
Options
Download
Email Patches
Plain Diff
Document configuration and build process (#362)
parent
c13f7f40
No related merge requests found
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
config/babel.dev.js
+12
-0
config/babel.dev.js
config/babel.prod.js
+13
-2
config/babel.prod.js
config/env.js
+3
-0
config/env.js
config/polyfills.js
+1
-0
config/polyfills.js
config/webpack.config.dev.js
+66
-2
config/webpack.config.dev.js
config/webpack.config.prod.js
+65
-5
config/webpack.config.prod.js
scripts/build.js
+7
-1
scripts/build.js
scripts/start.js
+36
-11
scripts/start.js
with
203 additions
and
21 deletions
+203
-21
config/babel.dev.js
+
12
-
0
View file @
c1a984d9
...
@@ -8,19 +8,31 @@
...
@@ -8,19 +8,31 @@
*/
*/
module
.
exports
=
{
module
.
exports
=
{
// Don't try to find .babelrc because we want to force this configuration.
babelrc
:
false
,
babelrc
:
false
,
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in OS temporary directory for faster rebuilds.
cacheDirectory
:
true
,
cacheDirectory
:
true
,
presets
:
[
presets
:
[
// let, const, destructuring, classes, modules
require
.
resolve
(
'
babel-preset-es2015
'
),
require
.
resolve
(
'
babel-preset-es2015
'
),
// exponentiation
require
.
resolve
(
'
babel-preset-es2016
'
),
require
.
resolve
(
'
babel-preset-es2016
'
),
// JSX, Flow
require
.
resolve
(
'
babel-preset-react
'
)
require
.
resolve
(
'
babel-preset-react
'
)
],
],
plugins
:
[
plugins
:
[
// function x(a, b, c,) { }
require
.
resolve
(
'
babel-plugin-syntax-trailing-function-commas
'
),
require
.
resolve
(
'
babel-plugin-syntax-trailing-function-commas
'
),
// await fetch()
require
.
resolve
(
'
babel-plugin-syntax-async-functions
'
),
require
.
resolve
(
'
babel-plugin-syntax-async-functions
'
),
// class { handleClick = () => { } }
require
.
resolve
(
'
babel-plugin-transform-class-properties
'
),
require
.
resolve
(
'
babel-plugin-transform-class-properties
'
),
// { ...todo, completed: true }
require
.
resolve
(
'
babel-plugin-transform-object-rest-spread
'
),
require
.
resolve
(
'
babel-plugin-transform-object-rest-spread
'
),
// function* () { yield 42; yield 43; }
require
.
resolve
(
'
babel-plugin-transform-regenerator
'
),
require
.
resolve
(
'
babel-plugin-transform-regenerator
'
),
// Polyfills the runtime needed for async/await and generators
[
require
.
resolve
(
'
babel-plugin-transform-runtime
'
),
{
[
require
.
resolve
(
'
babel-plugin-transform-runtime
'
),
{
helpers
:
false
,
helpers
:
false
,
polyfill
:
false
,
polyfill
:
false
,
...
...
This diff is collapsed.
Click to expand it.
config/babel.prod.js
+
13
-
2
View file @
c1a984d9
...
@@ -8,23 +8,34 @@
...
@@ -8,23 +8,34 @@
*/
*/
module
.
exports
=
{
module
.
exports
=
{
// Don't try to find .babelrc because we want to force this configuration.
babelrc
:
false
,
babelrc
:
false
,
presets
:
[
presets
:
[
// let, const, destructuring, classes, modules
require
.
resolve
(
'
babel-preset-es2015
'
),
require
.
resolve
(
'
babel-preset-es2015
'
),
// exponentiation
require
.
resolve
(
'
babel-preset-es2016
'
),
require
.
resolve
(
'
babel-preset-es2016
'
),
// JSX, Flow
require
.
resolve
(
'
babel-preset-react
'
)
require
.
resolve
(
'
babel-preset-react
'
)
],
],
plugins
:
[
plugins
:
[
// function x(a, b, c,) { }
require
.
resolve
(
'
babel-plugin-syntax-trailing-function-commas
'
),
require
.
resolve
(
'
babel-plugin-syntax-trailing-function-commas
'
),
// await fetch()
require
.
resolve
(
'
babel-plugin-syntax-async-functions
'
),
require
.
resolve
(
'
babel-plugin-syntax-async-functions
'
),
// class { handleClick = () => { } }
require
.
resolve
(
'
babel-plugin-transform-class-properties
'
),
require
.
resolve
(
'
babel-plugin-transform-class-properties
'
),
// { ...todo, completed: true }
require
.
resolve
(
'
babel-plugin-transform-object-rest-spread
'
),
require
.
resolve
(
'
babel-plugin-transform-object-rest-spread
'
),
require
.
resolve
(
'
babel-plugin-transform-react-constant-elements
'
),
// function* () { yield 42; yield 43; }
require
.
resolve
(
'
babel-plugin-transform-regenerator
'
),
require
.
resolve
(
'
babel-plugin-transform-regenerator
'
),
// Polyfills the runtime needed for async/await and generators
[
require
.
resolve
(
'
babel-plugin-transform-runtime
'
),
{
[
require
.
resolve
(
'
babel-plugin-transform-runtime
'
),
{
helpers
:
false
,
helpers
:
false
,
polyfill
:
false
,
polyfill
:
false
,
regenerator
:
true
regenerator
:
true
}]
}],
// Optimization: hoist JSX that never changes out of render()
require
.
resolve
(
'
babel-plugin-transform-react-constant-elements
'
)
]
]
};
};
This diff is collapsed.
Click to expand it.
config/env.js
+
3
-
0
View file @
c1a984d9
...
@@ -7,6 +7,9 @@
...
@@ -7,6 +7,9 @@
* 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.
*/
*/
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
var
REACT_APP
=
/^REACT_APP_/i
;
var
REACT_APP
=
/^REACT_APP_/i
;
var
NODE_ENV
=
JSON
.
stringify
(
process
.
env
.
NODE_ENV
||
'
development
'
);
var
NODE_ENV
=
JSON
.
stringify
(
process
.
env
.
NODE_ENV
||
'
development
'
);
...
...
This diff is collapsed.
Click to expand it.
config/polyfills.js
+
1
-
0
View file @
c1a984d9
...
@@ -6,4 +6,5 @@ if (typeof Promise === 'undefined') {
...
@@ -6,4 +6,5 @@ if (typeof Promise === 'undefined') {
window
.
Promise
=
require
(
'
promise/lib/es6-extensions.js
'
);
window
.
Promise
=
require
(
'
promise/lib/es6-extensions.js
'
);
}
}
// fetch() polyfill for making API calls.
require
(
'
whatwg-fetch
'
);
require
(
'
whatwg-fetch
'
);
This diff is collapsed.
Click to expand it.
config/webpack.config.dev.js
+
66
-
2
View file @
c1a984d9
...
@@ -16,22 +16,56 @@ var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeMo
...
@@ -16,22 +16,56 @@ var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeMo
var
paths
=
require
(
'
./paths
'
);
var
paths
=
require
(
'
./paths
'
);
var
env
=
require
(
'
./env
'
);
var
env
=
require
(
'
./env
'
);
// This is the development configuration.
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
module
.
exports
=
{
module
.
exports
=
{
// This makes the bundle appear split into separate modules in the devtools.
// We don't use source maps here because they can be confusing:
// https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875
// You may want 'cheap-module-source-map' instead if you prefer source maps.
devtool
:
'
eval
'
,
devtool
:
'
eval
'
,
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
entry
:
[
entry
:
[
// Include WebpackDevServer client. It connects to WebpackDevServer via
// sockets and waits for recompile notifications. When WebpackDevServer
// recompiles, it sends a message to the client by socket. If only CSS
// was changed, the app reload just the CSS. Otherwise, it will refresh.
// The "?/" bit at the end tells the client to look for the socket at
// the root path, i.e. /sockjs-node/. Otherwise visiting a client-side
// route like /todos/42 would make it wrongly request /todos/42/sockjs-node.
// The socket server is a part of WebpackDevServer which we are using.
// The /sockjs-node/ path I'm referring to is hardcoded in WebpackDevServer.
require
.
resolve
(
'
webpack-dev-server/client
'
)
+
'
?/
'
,
require
.
resolve
(
'
webpack-dev-server/client
'
)
+
'
?/
'
,
// Include Webpack hot module replacement runtime. Webpack is pretty
// low-level so we need to put all the pieces together. The runtime listens
// to the events received by the client above, and applies updates (such as
// new CSS) to the running application.
require
.
resolve
(
'
webpack/hot/dev-server
'
),
require
.
resolve
(
'
webpack/hot/dev-server
'
),
// We ship a few polyfills by default.
require
.
resolve
(
'
./polyfills
'
),
require
.
resolve
(
'
./polyfills
'
),
// Finally, this is your app's code:
path
.
join
(
paths
.
appSrc
,
'
index
'
)
path
.
join
(
paths
.
appSrc
,
'
index
'
)
// We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh.
],
],
output
:
{
output
:
{
// Next line is not used in dev but WebpackDevServer crashes without it:
// Next line is not used in dev but WebpackDevServer crashes without it:
path
:
paths
.
appBuild
,
path
:
paths
.
appBuild
,
// Add /* filename */ comments to generated require()s in the output.
pathinfo
:
true
,
pathinfo
:
true
,
// This does not produce a real file. It's just the virtual path that is
// served by WebpackDevServer in development. This is the JS bundle
// containing code from all our entry points, and the Webpack runtime.
filename
:
'
static/js/bundle.js
'
,
filename
:
'
static/js/bundle.js
'
,
// In development, we always serve from the root. This makes config easier.
publicPath
:
'
/
'
publicPath
:
'
/
'
},
},
resolve
:
{
resolve
:
{
// These are the reasonable defaults supported by the Node ecosystem.
extensions
:
[
'
.js
'
,
'
.json
'
,
''
],
extensions
:
[
'
.js
'
,
'
.json
'
,
''
],
alias
:
{
alias
:
{
// This `alias` section can be safely removed after ejection.
// This `alias` section can be safely removed after ejection.
...
@@ -45,11 +79,16 @@ module.exports = {
...
@@ -45,11 +79,16 @@ module.exports = {
'
babel-runtime/regenerator
'
:
require
.
resolve
(
'
babel-runtime/regenerator
'
)
'
babel-runtime/regenerator
'
:
require
.
resolve
(
'
babel-runtime/regenerator
'
)
}
}
},
},
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
// directory of `react-scripts` itself rather than the project directory.
// You can remove this after ejecting.
resolveLoader
:
{
resolveLoader
:
{
root
:
paths
.
ownNodeModules
,
root
:
paths
.
ownNodeModules
,
moduleTemplates
:
[
'
*-loader
'
]
moduleTemplates
:
[
'
*-loader
'
]
},
},
module
:
{
module
:
{
// First, run the linter.
// It's important to do this before Babel processes the JS.
preLoaders
:
[
preLoaders
:
[
{
{
test
:
/
\.
js$/
,
test
:
/
\.
js$/
,
...
@@ -58,22 +97,33 @@ module.exports = {
...
@@ -58,22 +97,33 @@ module.exports = {
}
}
],
],
loaders
:
[
loaders
:
[
// Process JS with Babel.
{
{
test
:
/
\.
js$/
,
test
:
/
\.
js$/
,
include
:
paths
.
appSrc
,
include
:
paths
.
appSrc
,
loader
:
'
babel
'
,
loader
:
'
babel
'
,
query
:
require
(
'
./babel.dev
'
)
query
:
require
(
'
./babel.dev
'
)
},
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
{
{
test
:
/
\.
css$/
,
test
:
/
\.
css$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
loader
:
'
style!css!postcss
'
loader
:
'
style!css!postcss
'
},
},
// JSON is not enabled by default in Webpack but both Node and Browserify
// allow it implicitly so we also enable it.
{
{
test
:
/
\.
json$/
,
test
:
/
\.
json$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
loader
:
'
json
'
loader
:
'
json
'
},
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
{
{
test
:
/
\.(
jpg|png|gif|eot|svg|ttf|woff|woff2
)(\?
.*
)?
$/
,
test
:
/
\.(
jpg|png|gif|eot|svg|ttf|woff|woff2
)(\?
.*
)?
$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
...
@@ -82,6 +132,8 @@ module.exports = {
...
@@ -82,6 +132,8 @@ module.exports = {
name
:
'
static/media/[name].[ext]
'
name
:
'
static/media/[name].[ext]
'
}
}
},
},
// "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests.
{
{
test
:
/
\.(
mp4|webm
)(\?
.*
)?
$/
,
test
:
/
\.(
mp4|webm
)(\?
.*
)?
$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
...
@@ -93,10 +145,12 @@ module.exports = {
...
@@ -93,10 +145,12 @@ module.exports = {
}
}
]
]
},
},
// Point ESLint to our predefined config.
eslint
:
{
eslint
:
{
configFile
:
path
.
join
(
__dirname
,
'
eslint.js
'
),
configFile
:
path
.
join
(
__dirname
,
'
eslint.js
'
),
useEslintrc
:
false
useEslintrc
:
false
},
},
// We use PostCSS for autoprefixing only.
postcss
:
function
()
{
postcss
:
function
()
{
return
[
return
[
autoprefixer
({
autoprefixer
({
...
@@ -104,21 +158,31 @@ module.exports = {
...
@@ -104,21 +158,31 @@ module.exports = {
'
>1%
'
,
'
>1%
'
,
'
last 4 versions
'
,
'
last 4 versions
'
,
'
Firefox ESR
'
,
'
Firefox ESR
'
,
'
not ie < 9
'
,
'
not ie < 9
'
,
// React doesn't support IE8 anyway
]
]
}),
}),
];
];
},
},
plugins
:
[
plugins
:
[
// Generates an `index.html` file with the <script> injected.
new
HtmlWebpackPlugin
({
new
HtmlWebpackPlugin
({
inject
:
true
,
inject
:
true
,
template
:
paths
.
appHtml
,
template
:
paths
.
appHtml
,
favicon
:
paths
.
appFavicon
,
favicon
:
paths
.
appFavicon
,
}),
}),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
new
webpack
.
DefinePlugin
(
env
),
new
webpack
.
DefinePlugin
(
env
),
//
Note: only CSS i
s currently
hot reloaded
//
This is necessary to emit hot update
s
(
currently
CSS only):
new
webpack
.
HotModuleReplacementPlugin
(),
new
webpack
.
HotModuleReplacementPlugin
(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebookincubator/create-react-app/issues/240
new
CaseSensitivePathsPlugin
(),
new
CaseSensitivePathsPlugin
(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebookincubator/create-react-app/issues/186
new
WatchMissingNodeModulesPlugin
(
paths
.
appNodeModules
)
new
WatchMissingNodeModulesPlugin
(
paths
.
appNodeModules
)
]
]
};
};
This diff is collapsed.
Click to expand it.
config/webpack.config.prod.js
+
65
-
5
View file @
c1a984d9
...
@@ -16,27 +16,51 @@ var url = require('url');
...
@@ -16,27 +16,51 @@ var url = require('url');
var
paths
=
require
(
'
./paths
'
);
var
paths
=
require
(
'
./paths
'
);
var
env
=
require
(
'
./env
'
);
var
env
=
require
(
'
./env
'
);
// Assert this just to be safe.
// Development builds of React are slow and not intended for production.
if
(
env
[
'
process.env.NODE_ENV
'
]
!==
'
"production"
'
)
{
throw
new
Error
(
'
Production builds must have NODE_ENV=production.
'
);
}
// We use "homepage" field to infer "public path" at which the app is served.
// Webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
var
homepagePath
=
require
(
paths
.
appPackageJson
).
homepage
;
var
homepagePath
=
require
(
paths
.
appPackageJson
).
homepage
;
var
publicPath
=
homepagePath
?
url
.
parse
(
homepagePath
).
pathname
:
'
/
'
;
var
publicPath
=
homepagePath
?
url
.
parse
(
homepagePath
).
pathname
:
'
/
'
;
if
(
!
publicPath
.
endsWith
(
'
/
'
))
{
if
(
!
publicPath
.
endsWith
(
'
/
'
))
{
//
Prevents
incorrect paths
in file-loader
//
If we don't do this, file assets will get
incorrect paths
.
publicPath
+=
'
/
'
;
publicPath
+=
'
/
'
;
}
}
// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
// The development configuration is different and lives in a separate file.
module
.
exports
=
{
module
.
exports
=
{
// Don't attempt to continue if there are any errors.
bail
:
true
,
bail
:
true
,
// We generate sourcemaps in production. This is slow but gives good results.
// You can exclude the *.map files from the build during deployment.
devtool
:
'
source-map
'
,
devtool
:
'
source-map
'
,
// In production, we only want to load the polyfills and the app code.
entry
:
[
entry
:
[
require
.
resolve
(
'
./polyfills
'
),
require
.
resolve
(
'
./polyfills
'
),
path
.
join
(
paths
.
appSrc
,
'
index
'
)
path
.
join
(
paths
.
appSrc
,
'
index
'
)
],
],
output
:
{
output
:
{
// The build folder.
path
:
paths
.
appBuild
,
path
:
paths
.
appBuild
,
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
// We don't currently advertise code splitting but Webpack supports it.
filename
:
'
static/js/[name].[chunkhash:8].js
'
,
filename
:
'
static/js/[name].[chunkhash:8].js
'
,
chunkFilename
:
'
static/js/[name].[chunkhash:8].chunk.js
'
,
chunkFilename
:
'
static/js/[name].[chunkhash:8].chunk.js
'
,
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath
:
publicPath
publicPath
:
publicPath
},
},
resolve
:
{
resolve
:
{
// These are the reasonable defaults supported by the Node ecosystem.
extensions
:
[
'
.js
'
,
'
.json
'
,
''
],
extensions
:
[
'
.js
'
,
'
.json
'
,
''
],
alias
:
{
alias
:
{
// This `alias` section can be safely removed after ejection.
// This `alias` section can be safely removed after ejection.
...
@@ -50,11 +74,16 @@ module.exports = {
...
@@ -50,11 +74,16 @@ module.exports = {
'
babel-runtime/regenerator
'
:
require
.
resolve
(
'
babel-runtime/regenerator
'
)
'
babel-runtime/regenerator
'
:
require
.
resolve
(
'
babel-runtime/regenerator
'
)
}
}
},
},
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
// directory of `react-scripts` itself rather than the project directory.
// You can remove this after ejecting.
resolveLoader
:
{
resolveLoader
:
{
root
:
paths
.
ownNodeModules
,
root
:
paths
.
ownNodeModules
,
moduleTemplates
:
[
'
*-loader
'
]
moduleTemplates
:
[
'
*-loader
'
]
},
},
module
:
{
module
:
{
// First, run the linter.
// It's important to do this before Babel processes the JS.
preLoaders
:
[
preLoaders
:
[
{
{
test
:
/
\.
js$/
,
test
:
/
\.
js$/
,
...
@@ -63,26 +92,44 @@ module.exports = {
...
@@ -63,26 +92,44 @@ module.exports = {
}
}
],
],
loaders
:
[
loaders
:
[
// Process JS with Babel.
{
{
test
:
/
\.
js$/
,
test
:
/
\.
js$/
,
include
:
paths
.
appSrc
,
include
:
paths
.
appSrc
,
loader
:
'
babel
'
,
loader
:
'
babel
'
,
query
:
require
(
'
./babel.prod
'
)
query
:
require
(
'
./babel.prod
'
)
},
},
// The notation here is somewhat confusing.
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader normally turns CSS into JS modules injecting <style>,
// but unlike in development configuration, we do something different.
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
// (second argument), then grabs the result CSS and puts it into a
// separate file in our build process. This way we actually ship
// a single CSS file in production instead of JS code injecting <style>
// tags. If you use code splitting, however, any async bundles will still
// use the "style" loader inside the async code so CSS from them won't be
// in the main CSS file.
{
{
test
:
/
\.
css$/
,
test
:
/
\.
css$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
//
D
isable autoprefixer in css-loader itself:
//
"?-autoprefixer" d
isable
s
autoprefixer in css-loader itself:
// https://github.com/webpack/css-loader/issues/281
// https://github.com/webpack/css-loader/issues/281
// We already have it thanks to postcss.
// We already have it thanks to postcss.
loader
:
ExtractTextPlugin
.
extract
(
'
style
'
,
'
css?-autoprefixer!postcss
'
)
loader
:
ExtractTextPlugin
.
extract
(
'
style
'
,
'
css?-autoprefixer!postcss
'
)
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
},
{
{
// JSON is not enabled by default in Webpack but both Node and Browserify
// allow it implicitly so we also enable it.
test
:
/
\.
json$/
,
test
:
/
\.
json$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
loader
:
'
json
'
loader
:
'
json
'
},
},
{
{
// "file" loader makes sure those assets end up in the `build` folder.
// When you `import` an asset, you get its filename.
test
:
/
\.(
jpg|png|gif|eot|svg|ttf|woff|woff2
)(\?
.*
)?
$/
,
test
:
/
\.(
jpg|png|gif|eot|svg|ttf|woff|woff2
)(\?
.*
)?
$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
loader
:
'
file
'
,
loader
:
'
file
'
,
...
@@ -90,6 +137,8 @@ module.exports = {
...
@@ -90,6 +137,8 @@ module.exports = {
name
:
'
static/media/[name].[hash:8].[ext]
'
name
:
'
static/media/[name].[hash:8].[ext]
'
}
}
},
},
// "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests.
{
{
test
:
/
\.(
mp4|webm
)(\?
.*
)?
$/
,
test
:
/
\.(
mp4|webm
)(\?
.*
)?
$/
,
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
include
:
[
paths
.
appSrc
,
paths
.
appNodeModules
],
...
@@ -101,12 +150,14 @@ module.exports = {
...
@@ -101,12 +150,14 @@ module.exports = {
}
}
]
]
},
},
// Point ESLint to our predefined config.
eslint
:
{
eslint
:
{
// TODO: consider separate config for production,
// TODO: consider separate config for production,
// e.g. to enable no-console and no-debugger only in prod.
// e.g. to enable no-console and no-debugger only in prod
uction
.
configFile
:
path
.
join
(
__dirname
,
'
eslint.js
'
),
configFile
:
path
.
join
(
__dirname
,
'
eslint.js
'
),
useEslintrc
:
false
useEslintrc
:
false
},
},
// We use PostCSS for autoprefixing only.
postcss
:
function
()
{
postcss
:
function
()
{
return
[
return
[
autoprefixer
({
autoprefixer
({
...
@@ -114,12 +165,13 @@ module.exports = {
...
@@ -114,12 +165,13 @@ module.exports = {
'
>1%
'
,
'
>1%
'
,
'
last 4 versions
'
,
'
last 4 versions
'
,
'
Firefox ESR
'
,
'
Firefox ESR
'
,
'
not ie < 9
'
,
'
not ie < 9
'
,
// React doesn't support IE8 anyway
]
]
}),
}),
];
];
},
},
plugins
:
[
plugins
:
[
// Generates an `index.html` file with the <script> injected.
new
HtmlWebpackPlugin
({
new
HtmlWebpackPlugin
({
inject
:
true
,
inject
:
true
,
template
:
paths
.
appHtml
,
template
:
paths
.
appHtml
,
...
@@ -137,12 +189,19 @@ module.exports = {
...
@@ -137,12 +189,19 @@ module.exports = {
minifyURLs
:
true
minifyURLs
:
true
}
}
}),
}),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `env.js`.
// It is absolutely essential that NODE_ENV was set to production here.
// Otherwise React will be compiled in the very slow development mode.
new
webpack
.
DefinePlugin
(
env
),
new
webpack
.
DefinePlugin
(
env
),
// This helps ensure the builds are consistent if source hasn't changed:
new
webpack
.
optimize
.
OccurrenceOrderPlugin
(),
new
webpack
.
optimize
.
OccurrenceOrderPlugin
(),
// Try to dedupe duplicated modules, if any:
new
webpack
.
optimize
.
DedupePlugin
(),
new
webpack
.
optimize
.
DedupePlugin
(),
// Minify the code.
new
webpack
.
optimize
.
UglifyJsPlugin
({
new
webpack
.
optimize
.
UglifyJsPlugin
({
compress
:
{
compress
:
{
screw_ie8
:
true
,
screw_ie8
:
true
,
// React doesn't support IE8
warnings
:
false
warnings
:
false
},
},
mangle
:
{
mangle
:
{
...
@@ -153,6 +212,7 @@ module.exports = {
...
@@ -153,6 +212,7 @@ module.exports = {
screw_ie8
:
true
screw_ie8
:
true
}
}
}),
}),
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
new
ExtractTextPlugin
(
'
static/css/[name].[contenthash:8].css
'
)
new
ExtractTextPlugin
(
'
static/css/[name].[contenthash:8].css
'
)
]
]
};
};
This diff is collapsed.
Click to expand it.
scripts/build.js
+
7
-
1
View file @
c1a984d9
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
* 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.
*/
*/
// Do this as the first thing so that any code reading it knows the right env.
process
.
env
.
NODE_ENV
=
'
production
'
;
process
.
env
.
NODE_ENV
=
'
production
'
;
var
chalk
=
require
(
'
chalk
'
);
var
chalk
=
require
(
'
chalk
'
);
...
@@ -21,12 +22,16 @@ var paths = require('../config/paths');
...
@@ -21,12 +22,16 @@ var paths = require('../config/paths');
var
recursive
=
require
(
'
recursive-readdir
'
);
var
recursive
=
require
(
'
recursive-readdir
'
);
var
stripAnsi
=
require
(
'
strip-ansi
'
);
var
stripAnsi
=
require
(
'
strip-ansi
'
);
// Input: /User/dan/app/build/static/js/main.82be8.js
// Output: /static/js/main.js
function
removeFileNameHash
(
fileName
)
{
function
removeFileNameHash
(
fileName
)
{
return
fileName
return
fileName
.
replace
(
paths
.
appBuild
,
''
)
.
replace
(
paths
.
appBuild
,
''
)
.
replace
(
/
\/?(
.*
)(\.\w
+
)(\.
js|
\.
css
)
/
,
(
match
,
p1
,
p2
,
p3
)
=>
p1
+
p3
);
.
replace
(
/
\/?(
.*
)(\.\w
+
)(\.
js|
\.
css
)
/
,
(
match
,
p1
,
p2
,
p3
)
=>
p1
+
p3
);
}
}
// Input: 1024, 2048
// Output: "(+1 KB)"
function
getDifferenceLabel
(
currentSize
,
previousSize
)
{
function
getDifferenceLabel
(
currentSize
,
previousSize
)
{
var
FIFTY_KILOBYTES
=
1024
*
50
;
var
FIFTY_KILOBYTES
=
1024
*
50
;
var
difference
=
currentSize
-
previousSize
;
var
difference
=
currentSize
-
previousSize
;
...
@@ -62,6 +67,7 @@ recursive(paths.appBuild, (err, fileNames) => {
...
@@ -62,6 +67,7 @@ recursive(paths.appBuild, (err, fileNames) => {
build
(
previousSizeMap
);
build
(
previousSizeMap
);
});
});
// Print a detailed summary of build files.
function
printFileSizes
(
stats
,
previousSizeMap
)
{
function
printFileSizes
(
stats
,
previousSizeMap
)
{
var
assets
=
stats
.
toJson
().
assets
var
assets
=
stats
.
toJson
().
assets
.
filter
(
asset
=>
/
\.(
js|css
)
$/
.
test
(
asset
.
name
))
.
filter
(
asset
=>
/
\.(
js|css
)
$/
.
test
(
asset
.
name
))
...
@@ -78,7 +84,6 @@ function printFileSizes(stats, previousSizeMap) {
...
@@ -78,7 +84,6 @@ function printFileSizes(stats, previousSizeMap) {
};
};
});
});
assets
.
sort
((
a
,
b
)
=>
b
.
size
-
a
.
size
);
assets
.
sort
((
a
,
b
)
=>
b
.
size
-
a
.
size
);
var
longestSizeLabelLength
=
Math
.
max
.
apply
(
null
,
var
longestSizeLabelLength
=
Math
.
max
.
apply
(
null
,
assets
.
map
(
a
=>
stripAnsi
(
a
.
sizeLabel
).
length
)
assets
.
map
(
a
=>
stripAnsi
(
a
.
sizeLabel
).
length
)
);
);
...
@@ -96,6 +101,7 @@ function printFileSizes(stats, previousSizeMap) {
...
@@ -96,6 +101,7 @@ function printFileSizes(stats, previousSizeMap) {
});
});
}
}
// Create the production build and print the deployment instructions.
function
build
(
previousSizeMap
)
{
function
build
(
previousSizeMap
)
{
console
.
log
(
'
Creating an optimized production build...
'
);
console
.
log
(
'
Creating an optimized production build...
'
);
webpack
(
config
).
run
((
err
,
stats
)
=>
{
webpack
(
config
).
run
((
err
,
stats
)
=>
{
...
...
This diff is collapsed.
Click to expand it.
scripts/start.js
+
36
-
11
View file @
c1a984d9
...
@@ -22,7 +22,7 @@ var prompt = require('./utils/prompt');
...
@@ -22,7 +22,7 @@ var prompt = require('./utils/prompt');
var
config
=
require
(
'
../config/webpack.config.dev
'
);
var
config
=
require
(
'
../config/webpack.config.dev
'
);
var
paths
=
require
(
'
../config/paths
'
);
var
paths
=
require
(
'
../config/paths
'
);
// Tools like Cloud9 rely on this
// Tools like Cloud9 rely on this
.
var
DEFAULT_PORT
=
process
.
env
.
PORT
||
3000
;
var
DEFAULT_PORT
=
process
.
env
.
PORT
||
3000
;
var
compiler
;
var
compiler
;
...
@@ -40,15 +40,13 @@ if (isSmokeTest) {
...
@@ -40,15 +40,13 @@ if (isSmokeTest) {
};
};
}
}
// Some custom utilities to prettify Webpack output.
// This is a little hacky.
// It would be easier if webpack provided a rich error object.
var
friendlySyntaxErrorLabel
=
'
Syntax error:
'
;
var
friendlySyntaxErrorLabel
=
'
Syntax error:
'
;
function
isLikelyASyntaxError
(
message
)
{
function
isLikelyASyntaxError
(
message
)
{
return
message
.
indexOf
(
friendlySyntaxErrorLabel
)
!==
-
1
;
return
message
.
indexOf
(
friendlySyntaxErrorLabel
)
!==
-
1
;
}
}
// This is a little hacky.
// It would be easier if webpack provided a rich error object.
function
formatMessage
(
message
)
{
function
formatMessage
(
message
)
{
return
message
return
message
// Make some common errors shorter:
// Make some common errors shorter:
...
@@ -69,17 +67,27 @@ function formatMessage(message) {
...
@@ -69,17 +67,27 @@ function formatMessage(message) {
}
}
function
clearConsole
()
{
function
clearConsole
()
{
// This seems to work best on Windows and other systems.
// The intention is to clear the output so you can focus on most recent build.
process
.
stdout
.
write
(
'
\
x1bc
'
);
process
.
stdout
.
write
(
'
\
x1bc
'
);
}
}
function
setupCompiler
(
port
)
{
function
setupCompiler
(
port
)
{
// "Compiler" is a low-level interface to Webpack.
// It lets us listen to some events and provide our own custom messages.
compiler
=
webpack
(
config
,
handleCompile
);
compiler
=
webpack
(
config
,
handleCompile
);
// "invalid" event fires when you have changed a file, and Webpack is
// recompiling a bundle. WebpackDevServer takes care to pause serving the
// bundle, so if you refresh, it'll wait instead of serving the old one.
// "invalid" is short for "bundle invalidated", it doesn't imply any errors.
compiler
.
plugin
(
'
invalid
'
,
function
()
{
compiler
.
plugin
(
'
invalid
'
,
function
()
{
clearConsole
();
clearConsole
();
console
.
log
(
'
Compiling...
'
);
console
.
log
(
'
Compiling...
'
);
});
});
// "done" event fires when Webpack has finished recompiling the bundle.
// Whether or not you have warnings or errors, you will get this event.
compiler
.
plugin
(
'
done
'
,
function
(
stats
)
{
compiler
.
plugin
(
'
done
'
,
function
(
stats
)
{
clearConsole
();
clearConsole
();
var
hasErrors
=
stats
.
hasErrors
();
var
hasErrors
=
stats
.
hasErrors
();
...
@@ -94,10 +102,12 @@ function setupCompiler(port) {
...
@@ -94,10 +102,12 @@ function setupCompiler(port) {
console
.
log
(
'
Note that the development build is not optimized.
'
);
console
.
log
(
'
Note that the development build is not optimized.
'
);
console
.
log
(
'
To create a production build, use
'
+
chalk
.
cyan
(
'
npm run build
'
)
+
'
.
'
);
console
.
log
(
'
To create a production build, use
'
+
chalk
.
cyan
(
'
npm run build
'
)
+
'
.
'
);
console
.
log
();
console
.
log
();
return
;
return
;
}
}
// We have switched off the default Webpack output in WebpackDevServer
// options so we are going to "massage" the warnings and errors and present
// them in a readable focused way.
var
json
=
stats
.
toJson
();
var
json
=
stats
.
toJson
();
var
formattedErrors
=
json
.
errors
.
map
(
message
=>
var
formattedErrors
=
json
.
errors
.
map
(
message
=>
'
Error in
'
+
formatMessage
(
message
)
'
Error in
'
+
formatMessage
(
message
)
...
@@ -105,7 +115,6 @@ function setupCompiler(port) {
...
@@ -105,7 +115,6 @@ function setupCompiler(port) {
var
formattedWarnings
=
json
.
warnings
.
map
(
message
=>
var
formattedWarnings
=
json
.
warnings
.
map
(
message
=>
'
Warning in
'
+
formatMessage
(
message
)
'
Warning in
'
+
formatMessage
(
message
)
);
);
if
(
hasErrors
)
{
if
(
hasErrors
)
{
console
.
log
(
chalk
.
red
(
'
Failed to compile.
'
));
console
.
log
(
chalk
.
red
(
'
Failed to compile.
'
));
console
.
log
();
console
.
log
();
...
@@ -122,7 +131,6 @@ function setupCompiler(port) {
...
@@ -122,7 +131,6 @@ function setupCompiler(port) {
// If errors exist, ignore warnings.
// If errors exist, ignore warnings.
return
;
return
;
}
}
if
(
hasWarnings
)
{
if
(
hasWarnings
)
{
console
.
log
(
chalk
.
yellow
(
'
Compiled with warnings.
'
));
console
.
log
(
chalk
.
yellow
(
'
Compiled with warnings.
'
));
console
.
log
();
console
.
log
();
...
@@ -130,7 +138,7 @@ function setupCompiler(port) {
...
@@ -130,7 +138,7 @@ function setupCompiler(port) {
console
.
log
(
message
);
console
.
log
(
message
);
console
.
log
();
console
.
log
();
});
});
// Teach some ESLint tricks.
console
.
log
(
'
You may use special comments to disable some warnings.
'
);
console
.
log
(
'
You may use special comments to disable some warnings.
'
);
console
.
log
(
'
Use
'
+
chalk
.
yellow
(
'
// eslint-disable-next-line
'
)
+
'
to ignore the next line.
'
);
console
.
log
(
'
Use
'
+
chalk
.
yellow
(
'
// eslint-disable-next-line
'
)
+
'
to ignore the next line.
'
);
console
.
log
(
'
Use
'
+
chalk
.
yellow
(
'
/* eslint-disable */
'
)
+
'
to ignore all warnings in a file.
'
);
console
.
log
(
'
Use
'
+
chalk
.
yellow
(
'
/* eslint-disable */
'
)
+
'
to ignore all warnings in a file.
'
);
...
@@ -207,14 +215,29 @@ function addMiddleware(devServer) {
...
@@ -207,14 +215,29 @@ function addMiddleware(devServer) {
function
runDevServer
(
port
)
{
function
runDevServer
(
port
)
{
var
devServer
=
new
WebpackDevServer
(
compiler
,
{
var
devServer
=
new
WebpackDevServer
(
compiler
,
{
hot
:
true
,
// Note: only CSS is currently hot reloaded
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
// for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point
// in the Webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser.
hot
:
true
,
// It is important to tell WebpackDevServer to use the same "root" path
// as we specified in the config. In development, we always serve from /.
publicPath
:
config
.
output
.
publicPath
,
publicPath
:
config
.
output
.
publicPath
,
// WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.plugin` calls above.
quiet
:
true
,
quiet
:
true
,
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebookincubator/create-react-app/issues/293
watchOptions
:
{
watchOptions
:
{
ignored
:
/node_modules/
ignored
:
/node_modules/
}
}
});
});
// Our custom middleware proxies requests to /index.html or a remote API.
addMiddleware
(
devServer
);
addMiddleware
(
devServer
);
// Launch WebpackDevServer.
devServer
.
listen
(
port
,
(
err
,
result
)
=>
{
devServer
.
listen
(
port
,
(
err
,
result
)
=>
{
if
(
err
)
{
if
(
err
)
{
return
console
.
log
(
err
);
return
console
.
log
(
err
);
...
@@ -232,6 +255,8 @@ function run(port) {
...
@@ -232,6 +255,8 @@ function run(port) {
runDevServer
(
port
);
runDevServer
(
port
);
}
}
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `detect()` Promise resolves to the next free port.
detect
(
DEFAULT_PORT
).
then
(
port
=>
{
detect
(
DEFAULT_PORT
).
then
(
port
=>
{
if
(
port
===
DEFAULT_PORT
)
{
if
(
port
===
DEFAULT_PORT
)
{
run
(
port
);
run
(
port
);
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Snippets