@@ -16,22 +16,56 @@ var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeMo
16
16
var paths = require ( './paths' ) ;
17
17
var env = require ( './env' ) ;
18
18
19
+ // This is the development configuration.
20
+ // It is focused on developer experience and fast rebuilds.
21
+ // The production configuration is different and lives in a separate file.
19
22
module . exports = {
23
+ // This makes the bundle appear split into separate modules in the devtools.
24
+ // We don't use source maps here because they can be confusing:
25
+ // https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875
26
+ // You may want 'cheap-module-source-map' instead if you prefer source maps.
20
27
devtool : 'eval' ,
28
+ // These are the "entry points" to our application.
29
+ // This means they will be the "root" imports that are included in JS bundle.
30
+ // The first two entry points enable "hot" CSS and auto-refreshes for JS.
21
31
entry : [
32
+ // Include WebpackDevServer client. It connects to WebpackDevServer via
33
+ // sockets and waits for recompile notifications. When WebpackDevServer
34
+ // recompiles, it sends a message to the client by socket. If only CSS
35
+ // was changed, the app reload just the CSS. Otherwise, it will refresh.
36
+ // The "?/" bit at the end tells the client to look for the socket at
37
+ // the root path, i.e. /sockjs-node/. Otherwise visiting a client-side
38
+ // route like /todos/42 would make it wrongly request /todos/42/sockjs-node.
39
+ // The socket server is a part of WebpackDevServer which we are using.
40
+ // The /sockjs-node/ path I'm referring to is hardcoded in WebpackDevServer.
22
41
require . resolve ( 'webpack-dev-server/client' ) + '?/' ,
42
+ // Include Webpack hot module replacement runtime. Webpack is pretty
43
+ // low-level so we need to put all the pieces together. The runtime listens
44
+ // to the events received by the client above, and applies updates (such as
45
+ // new CSS) to the running application.
23
46
require . resolve ( 'webpack/hot/dev-server' ) ,
47
+ // We ship a few polyfills by default.
24
48
require . resolve ( './polyfills' ) ,
49
+ // Finally, this is your app's code:
25
50
path . join ( paths . appSrc , 'index' )
51
+ // We include the app code last so that if there is a runtime error during
52
+ // initialization, it doesn't blow up the WebpackDevServer client, and
53
+ // changing JS code would still trigger a refresh.
26
54
] ,
27
55
output : {
28
56
// Next line is not used in dev but WebpackDevServer crashes without it:
29
57
path : paths . appBuild ,
58
+ // Add /* filename */ comments to generated require()s in the output.
30
59
pathinfo : true ,
60
+ // This does not produce a real file. It's just the virtual path that is
61
+ // served by WebpackDevServer in development. This is the JS bundle
62
+ // containing code from all our entry points, and the Webpack runtime.
31
63
filename : 'static/js/bundle.js' ,
64
+ // In development, we always serve from the root. This makes config easier.
32
65
publicPath : '/'
33
66
} ,
34
67
resolve : {
68
+ // These are the reasonable defaults supported by the Node ecosystem.
35
69
extensions : [ '.js' , '.json' , '' ] ,
36
70
alias : {
37
71
// This `alias` section can be safely removed after ejection.
@@ -45,11 +79,16 @@ module.exports = {
45
79
'babel-runtime/regenerator' : require . resolve ( 'babel-runtime/regenerator' )
46
80
}
47
81
} ,
82
+ // Resolve loaders (webpack plugins for CSS, images, transpilation) from the
83
+ // directory of `react-scripts` itself rather than the project directory.
84
+ // You can remove this after ejecting.
48
85
resolveLoader : {
49
86
root : paths . ownNodeModules ,
50
87
moduleTemplates : [ '*-loader' ]
51
88
} ,
52
89
module : {
90
+ // First, run the linter.
91
+ // It's important to do this before Babel processes the JS.
53
92
preLoaders : [
54
93
{
55
94
test : / \. j s $ / ,
@@ -58,22 +97,33 @@ module.exports = {
58
97
}
59
98
] ,
60
99
loaders : [
100
+ // Process JS with Babel.
61
101
{
62
102
test : / \. j s $ / ,
63
103
include : paths . appSrc ,
64
104
loader : 'babel' ,
65
105
query : require ( './babel.dev' )
66
106
} ,
107
+ // "postcss" loader applies autoprefixer to our CSS.
108
+ // "css" loader resolves paths in CSS and adds assets as dependencies.
109
+ // "style" loader turns CSS into JS modules that inject <style> tags.
110
+ // In production, we use a plugin to extract that CSS to a file, but
111
+ // in development "style" loader enables hot editing of CSS.
67
112
{
68
113
test : / \. c s s $ / ,
69
114
include : [ paths . appSrc , paths . appNodeModules ] ,
70
115
loader : 'style!css!postcss'
71
116
} ,
117
+ // JSON is not enabled by default in Webpack but both Node and Browserify
118
+ // allow it implicitly so we also enable it.
72
119
{
73
120
test : / \. j s o n $ / ,
74
121
include : [ paths . appSrc , paths . appNodeModules ] ,
75
122
loader : 'json'
76
123
} ,
124
+ // "file" loader makes sure those assets get served by WebpackDevServer.
125
+ // When you `import` an asset, you get its (virtual) filename.
126
+ // In production, they would get copied to the `build` folder.
77
127
{
78
128
test : / \. ( j p g | p n g | g i f | e o t | s v g | t t f | w o f f | w o f f 2 ) ( \? .* ) ? $ / ,
79
129
include : [ paths . appSrc , paths . appNodeModules ] ,
@@ -82,6 +132,8 @@ module.exports = {
82
132
name : 'static/media/[name].[ext]'
83
133
}
84
134
} ,
135
+ // "url" loader works just like "file" loader but it also embeds
136
+ // assets smaller than specified size as data URLs to avoid requests.
85
137
{
86
138
test : / \. ( m p 4 | w e b m ) ( \? .* ) ? $ / ,
87
139
include : [ paths . appSrc , paths . appNodeModules ] ,
@@ -93,32 +145,44 @@ module.exports = {
93
145
}
94
146
]
95
147
} ,
148
+ // Point ESLint to our predefined config.
96
149
eslint : {
97
150
configFile : path . join ( __dirname , 'eslint.js' ) ,
98
151
useEslintrc : false
99
152
} ,
153
+ // We use PostCSS for autoprefixing only.
100
154
postcss : function ( ) {
101
155
return [
102
156
autoprefixer ( {
103
157
browsers : [
104
158
'>1%' ,
105
159
'last 4 versions' ,
106
160
'Firefox ESR' ,
107
- 'not ie < 9' ,
161
+ 'not ie < 9' , // React doesn't support IE8 anyway
108
162
]
109
163
} ) ,
110
164
] ;
111
165
} ,
112
166
plugins : [
167
+ // Generates an `index.html` file with the <script> injected.
113
168
new HtmlWebpackPlugin ( {
114
169
inject : true ,
115
170
template : paths . appHtml ,
116
171
favicon : paths . appFavicon ,
117
172
} ) ,
173
+ // Makes some environment variables available to the JS code, for example:
174
+ // if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
118
175
new webpack . DefinePlugin ( env ) ,
119
- // Note: only CSS is currently hot reloaded
176
+ // This is necessary to emit hot updates (currently CSS only):
120
177
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
121
181
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
122
186
new WatchMissingNodeModulesPlugin ( paths . appNodeModules )
123
187
]
124
188
} ;
0 commit comments