@@ -15,22 +15,56 @@ var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
15
15
var WatchMissingNodeModulesPlugin = require ( '../scripts/utils/WatchMissingNodeModulesPlugin' ) ;
16
16
var paths = require ( './paths' ) ;
17
17
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.
18
21
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.
19
26
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.
20
30
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.
21
40
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.
22
45
require . resolve ( 'webpack/hot/dev-server' ) ,
46
+ // We ship a few polyfills by default.
23
47
require . resolve ( './polyfills' ) ,
48
+ // Finally, this is your app's code:
24
49
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.
25
53
] ,
26
54
output : {
27
55
// Next line is not used in dev but WebpackDevServer crashes without it:
28
56
path : paths . appBuild ,
57
+ // Add /* filename */ comments to generated require()s in the output.
29
58
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.
30
62
filename : 'static/js/bundle.js' ,
63
+ // In development, we always serve from the root. This makes config easier.
31
64
publicPath : '/'
32
65
} ,
33
66
resolve : {
67
+ // These are the reasonable defaults supported by the Node ecosystem.
34
68
extensions : [ '.js' , '.json' , '' ] ,
35
69
alias : {
36
70
// This `alias` section can be safely removed after ejection.
@@ -44,11 +78,16 @@ module.exports = {
44
78
'babel-runtime/regenerator' : require . resolve ( 'babel-runtime/regenerator' )
45
79
}
46
80
} ,
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.
47
84
resolveLoader : {
48
85
root : paths . ownNodeModules ,
49
86
moduleTemplates : [ '*-loader' ]
50
87
} ,
51
88
module : {
89
+ // First, run the linter.
90
+ // It's important to do this before Babel processes the JS.
52
91
preLoaders : [
53
92
{
54
93
test : / \. j s $ / ,
@@ -57,22 +96,33 @@ module.exports = {
57
96
}
58
97
] ,
59
98
loaders : [
99
+ // Process JS with Babel.
60
100
{
61
101
test : / \. j s $ / ,
62
102
include : paths . appSrc ,
63
103
loader : 'babel' ,
64
104
query : require ( './babel.dev' )
65
105
} ,
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.
66
111
{
67
112
test : / \. c s s $ / ,
68
113
include : [ paths . appSrc , paths . appNodeModules ] ,
69
114
loader : 'style!css!postcss'
70
115
} ,
116
+ // JSON is not enabled by default in Webpack but both Node and Browserify
117
+ // allow it implicitly so we also enable it.
71
118
{
72
119
test : / \. j s o n $ / ,
73
120
include : [ paths . appSrc , paths . appNodeModules ] ,
74
121
loader : 'json'
75
122
} ,
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.
76
126
{
77
127
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 ) ( \? .* ) ? $ / ,
78
128
include : [ paths . appSrc , paths . appNodeModules ] ,
@@ -81,6 +131,8 @@ module.exports = {
81
131
name : 'static/media/[name].[ext]'
82
132
}
83
133
} ,
134
+ // "url" loader works just like "file" loader but it also embeds
135
+ // assets smaller than specified size as data URLs to avoid requests.
84
136
{
85
137
test : / \. ( m p 4 | w e b m ) ( \? .* ) ? $ / ,
86
138
include : [ paths . appSrc , paths . appNodeModules ] ,
@@ -92,32 +144,45 @@ module.exports = {
92
144
}
93
145
]
94
146
} ,
147
+ // Point ESLint to our predefined config.
95
148
eslint : {
96
149
configFile : path . join ( __dirname , 'eslint.js' ) ,
97
150
useEslintrc : false
98
151
} ,
152
+ // We use PostCSS for autoprefixing only.
99
153
postcss : function ( ) {
100
154
return [
101
155
autoprefixer ( {
102
156
browsers : [
103
157
'>1%' ,
104
158
'last 4 versions' ,
105
159
'Firefox ESR' ,
106
- 'not ie < 9' ,
160
+ 'not ie < 9' , // React doesn't support IE8 anyway
107
161
]
108
162
} ) ,
109
163
] ;
110
164
} ,
111
165
plugins : [
166
+ // Generates an `index.html` file with the <script> injected.
112
167
new HtmlWebpackPlugin ( {
113
168
inject : true ,
114
169
template : paths . appHtml ,
115
170
favicon : paths . appFavicon ,
116
171
} ) ,
172
+ // Makes the environment available to the JS code, for example:
173
+ // if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
117
174
new webpack . DefinePlugin ( { 'process.env.NODE_ENV' : '"development"' } ) ,
118
175
// Note: only CSS is currently hot reloaded
176
+ // This is necessary to emit hot updates (currently CSS only):
119
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
120
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
121
186
new WatchMissingNodeModulesPlugin ( paths . appNodeModules )
122
187
]
123
188
} ;
0 commit comments