Skip to content

Commit 8e16295

Browse files
committed
Document configuration and build process (#362)
1 parent 6fb2667 commit 8e16295

File tree

7 files changed

+205
-38
lines changed

7 files changed

+205
-38
lines changed

config/babel.dev.js

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,31 @@
88
*/
99

1010
module.exports = {
11+
// Don't try to find .babelrc because we want to force this configuration.
1112
babelrc: false,
13+
// This is a feature of `babel-loader` for webpack (not Babel itself).
14+
// It enables caching results in OS temporary directory for faster rebuilds.
1215
cacheDirectory: true,
1316
presets: [
14-
'babel-preset-es2015',
15-
'babel-preset-es2016',
16-
'babel-preset-react'
17-
].map(require.resolve),
17+
// let, const, destructuring, classes, modules
18+
require.resolve('babel-preset-es2015'),
19+
// exponentiation
20+
require.resolve('babel-preset-es2016'),
21+
// JSX, Flow
22+
require.resolve('babel-preset-react')
23+
],
1824
plugins: [
19-
'babel-plugin-syntax-trailing-function-commas',
20-
'babel-plugin-transform-class-properties',
21-
'babel-plugin-transform-object-rest-spread'
22-
].map(require.resolve).concat([
25+
// function x(a, b, c,) { }
26+
require.resolve('babel-plugin-syntax-trailing-function-commas'),
27+
// class { handleClick = () => { } }
28+
require.resolve('babel-plugin-transform-class-properties'),
29+
// { ...todo, completed: true }
30+
require.resolve('babel-plugin-transform-object-rest-spread'),
31+
// Polyfills the runtime needed for generators
2332
[require.resolve('babel-plugin-transform-runtime'), {
2433
helpers: false,
2534
polyfill: false,
2635
regenerator: true
2736
}]
28-
])
37+
]
2938
};

config/babel.prod.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,30 @@
88
*/
99

1010
module.exports = {
11+
// Don't try to find .babelrc because we want to force this configuration.
1112
babelrc: false,
1213
presets: [
13-
'babel-preset-es2015',
14-
'babel-preset-es2016',
15-
'babel-preset-react'
16-
].map(require.resolve),
14+
// let, const, destructuring, classes, modules
15+
require.resolve('babel-preset-es2015'),
16+
// exponentiation
17+
require.resolve('babel-preset-es2016'),
18+
// JSX, Flow
19+
require.resolve('babel-preset-react')
20+
],
1721
plugins: [
18-
'babel-plugin-syntax-trailing-function-commas',
19-
'babel-plugin-transform-class-properties',
20-
'babel-plugin-transform-object-rest-spread',
21-
'babel-plugin-transform-react-constant-elements',
22-
].map(require.resolve).concat([
22+
// function x(a, b, c,) { }
23+
require.resolve('babel-plugin-syntax-trailing-function-commas'),
24+
// class { handleClick = () => { } }
25+
require.resolve('babel-plugin-transform-class-properties'),
26+
// { ...todo, completed: true }
27+
require.resolve('babel-plugin-transform-object-rest-spread'),
28+
// Polyfills the runtime needed for generators
2329
[require.resolve('babel-plugin-transform-runtime'), {
2430
helpers: false,
2531
polyfill: false,
2632
regenerator: true
27-
}]
28-
])
33+
}],
34+
// Optimization: hoist JSX that never changes out of render()
35+
require.resolve('babel-plugin-transform-react-constant-elements')
36+
],
2937
};

config/polyfills.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ if (typeof Promise === 'undefined') {
66
window.Promise = require('promise/lib/es6-extensions.js');
77
}
88

9+
// fetch() polyfill for making API calls.
910
require('whatwg-fetch');

config/webpack.config.dev.js

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,56 @@ var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
1515
var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeModulesPlugin');
1616
var paths = require('./paths');
1717

18+
// This is the development configuration.
19+
// It is focused on developer experience and fast rebuilds.
20+
// The production configuration is different and lives in a separate file.
1821
module.exports = {
22+
// This makes the bundle appear split into separate modules in the devtools.
23+
// We don't use source maps here because they can be confusing:
24+
// https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875
25+
// You may want 'cheap-module-source-map' instead if you prefer source maps.
1926
devtool: 'eval',
27+
// These are the "entry points" to our application.
28+
// This means they will be the "root" imports that are included in JS bundle.
29+
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
2030
entry: [
31+
// Include WebpackDevServer client. It connects to WebpackDevServer via
32+
// sockets and waits for recompile notifications. When WebpackDevServer
33+
// recompiles, it sends a message to the client by socket. If only CSS
34+
// was changed, the app reload just the CSS. Otherwise, it will refresh.
35+
// The "?/" bit at the end tells the client to look for the socket at
36+
// the root path, i.e. /sockjs-node/. Otherwise visiting a client-side
37+
// route like /todos/42 would make it wrongly request /todos/42/sockjs-node.
38+
// The socket server is a part of WebpackDevServer which we are using.
39+
// The /sockjs-node/ path I'm referring to is hardcoded in WebpackDevServer.
2140
require.resolve('webpack-dev-server/client') + '?/',
41+
// Include Webpack hot module replacement runtime. Webpack is pretty
42+
// low-level so we need to put all the pieces together. The runtime listens
43+
// to the events received by the client above, and applies updates (such as
44+
// new CSS) to the running application.
2245
require.resolve('webpack/hot/dev-server'),
46+
// We ship a few polyfills by default.
2347
require.resolve('./polyfills'),
48+
// Finally, this is your app's code:
2449
path.join(paths.appSrc, 'index')
50+
// We include the app code last so that if there is a runtime error during
51+
// initialization, it doesn't blow up the WebpackDevServer client, and
52+
// changing JS code would still trigger a refresh.
2553
],
2654
output: {
2755
// Next line is not used in dev but WebpackDevServer crashes without it:
2856
path: paths.appBuild,
57+
// Add /* filename */ comments to generated require()s in the output.
2958
pathinfo: true,
59+
// This does not produce a real file. It's just the virtual path that is
60+
// served by WebpackDevServer in development. This is the JS bundle
61+
// containing code from all our entry points, and the Webpack runtime.
3062
filename: 'static/js/bundle.js',
63+
// In development, we always serve from the root. This makes config easier.
3164
publicPath: '/'
3265
},
3366
resolve: {
67+
// These are the reasonable defaults supported by the Node ecosystem.
3468
extensions: ['.js', '.json', ''],
3569
alias: {
3670
// This `alias` section can be safely removed after ejection.
@@ -44,11 +78,16 @@ module.exports = {
4478
'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator')
4579
}
4680
},
81+
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
82+
// directory of `react-scripts` itself rather than the project directory.
83+
// You can remove this after ejecting.
4784
resolveLoader: {
4885
root: paths.ownNodeModules,
4986
moduleTemplates: ['*-loader']
5087
},
5188
module: {
89+
// First, run the linter.
90+
// It's important to do this before Babel processes the JS.
5291
preLoaders: [
5392
{
5493
test: /\.js$/,
@@ -57,22 +96,33 @@ module.exports = {
5796
}
5897
],
5998
loaders: [
99+
// Process JS with Babel.
60100
{
61101
test: /\.js$/,
62102
include: paths.appSrc,
63103
loader: 'babel',
64104
query: require('./babel.dev')
65105
},
106+
// "postcss" loader applies autoprefixer to our CSS.
107+
// "css" loader resolves paths in CSS and adds assets as dependencies.
108+
// "style" loader turns CSS into JS modules that inject <style> tags.
109+
// In production, we use a plugin to extract that CSS to a file, but
110+
// in development "style" loader enables hot editing of CSS.
66111
{
67112
test: /\.css$/,
68113
include: [paths.appSrc, paths.appNodeModules],
69114
loader: 'style!css!postcss'
70115
},
116+
// JSON is not enabled by default in Webpack but both Node and Browserify
117+
// allow it implicitly so we also enable it.
71118
{
72119
test: /\.json$/,
73120
include: [paths.appSrc, paths.appNodeModules],
74121
loader: 'json'
75122
},
123+
// "file" loader makes sure those assets get served by WebpackDevServer.
124+
// When you `import` an asset, you get its (virtual) filename.
125+
// In production, they would get copied to the `build` folder.
76126
{
77127
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
78128
include: [paths.appSrc, paths.appNodeModules],
@@ -81,6 +131,8 @@ module.exports = {
81131
name: 'static/media/[name].[ext]'
82132
}
83133
},
134+
// "url" loader works just like "file" loader but it also embeds
135+
// assets smaller than specified size as data URLs to avoid requests.
84136
{
85137
test: /\.(mp4|webm)(\?.*)?$/,
86138
include: [paths.appSrc, paths.appNodeModules],
@@ -92,32 +144,45 @@ module.exports = {
92144
}
93145
]
94146
},
147+
// Point ESLint to our predefined config.
95148
eslint: {
96149
configFile: path.join(__dirname, 'eslint.js'),
97150
useEslintrc: false
98151
},
152+
// We use PostCSS for autoprefixing only.
99153
postcss: function() {
100154
return [
101155
autoprefixer({
102156
browsers: [
103157
'>1%',
104158
'last 4 versions',
105159
'Firefox ESR',
106-
'not ie < 9',
160+
'not ie < 9', // React doesn't support IE8 anyway
107161
]
108162
}),
109163
];
110164
},
111165
plugins: [
166+
// Generates an `index.html` file with the <script> injected.
112167
new HtmlWebpackPlugin({
113168
inject: true,
114169
template: paths.appHtml,
115170
favicon: paths.appFavicon,
116171
}),
172+
// Makes the environment available to the JS code, for example:
173+
// if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
117174
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }),
118175
// Note: only CSS is currently hot reloaded
176+
// This is necessary to emit hot updates (currently CSS only):
119177
new webpack.HotModuleReplacementPlugin(),
178+
// Watcher doesn't work well if you mistype casing in a path so we use
179+
// a plugin that prints an error when you attempt to do this.
180+
// See https://github.com/facebookincubator/create-react-app/issues/240
120181
new CaseSensitivePathsPlugin(),
182+
// If you require a missing module and then `npm install` it, you still have
183+
// to restart the development server for Webpack to discover it. This plugin
184+
// makes the discovery automatic so you don't have to restart.
185+
// See https://github.com/facebookincubator/create-react-app/issues/186
121186
new WatchMissingNodeModulesPlugin(paths.appNodeModules)
122187
]
123188
};

0 commit comments

Comments
 (0)