Skip to content

Commit 447c559

Browse files
Furizaakasperpeulen
authored andcommitted
Use Rule.oneOf to resolve correct loader (facebook#2747)
* Use oneOf to resolve correct loader * Add html and json fallthrough again * Use oneOf to resolve correct loader in dev * Document file-loaders `js` exclusion * Remove `jsx` from exclusion in prod config
1 parent f64c910 commit 447c559

File tree

2 files changed

+175
-171
lines changed

2 files changed

+175
-171
lines changed

packages/react-scripts/config/webpack.config.dev.js

+78-76
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ const env = getClientEnvironment(publicUrl);
3636
let supportedBrowsers = require(paths.appPackageJson).browserslist;
3737
if (!supportedBrowsers || Object.keys(supportedBrowsers).length === 0) {
3838
// Assign default browsers when browserslist is not specified
39-
supportedBrowsers =
40-
"browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway]";
39+
supportedBrowsers = [
40+
'>1%',
41+
'last 4 versions',
42+
'Firefox ESR',
43+
'not ie < 9', // React doesn't support IE8 anyway
44+
];
4145
}
4246

4347
// This is the development configuration.
@@ -158,92 +162,90 @@ module.exports = {
158162
],
159163
include: paths.appSrc,
160164
},
161-
// ** ADDING/UPDATING LOADERS **
162-
// The "file" loader handles all assets unless explicitly excluded.
163-
// The `exclude` list *must* be updated with every change to loader extensions.
164-
// When adding a new loader, you must add its `test`
165-
// as a new entry in the `exclude` list for "file" loader.
166-
167-
// "file" loader makes sure those assets get served by WebpackDevServer.
168-
// When you `import` an asset, you get its (virtual) filename.
169-
// In production, they would get copied to the `build` folder.
170-
{
171-
exclude: [
172-
/\.html$/,
173-
/\.(js|jsx)$/,
174-
/\.css$/,
175-
/\.json$/,
176-
/\.bmp$/,
177-
/\.gif$/,
178-
/\.jpe?g$/,
179-
/\.png$/,
180-
],
181-
loader: require.resolve('file-loader'),
182-
options: {
183-
name: 'static/media/[name].[hash:8].[ext]',
184-
},
185-
},
186-
// "url" loader works like "file" loader except that it embeds assets
187-
// smaller than specified limit in bytes as data URLs to avoid requests.
188-
// A missing `test` is equivalent to a match.
189-
{
190-
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
191-
loader: require.resolve('url-loader'),
192-
options: {
193-
limit: 10000,
194-
name: 'static/media/[name].[hash:8].[ext]',
195-
},
196-
},
197-
// Process JS with Babel.
198165
{
199-
test: /\.(js|jsx)$/,
200-
include: paths.appSrc,
201-
loader: require.resolve('babel-loader'),
202-
options: {
203-
// @remove-on-eject-begin
204-
babelrc: false,
205-
presets: [require.resolve('babel-preset-react-app')],
206-
// @remove-on-eject-end
207-
// This is a feature of `babel-loader` for webpack (not Babel itself).
208-
// It enables caching results in ./node_modules/.cache/babel-loader/
209-
// directory for faster rebuilds.
210-
cacheDirectory: true,
211-
},
212-
},
213-
// "postcss" loader applies autoprefixer to our CSS.
214-
// "css" loader resolves paths in CSS and adds assets as dependencies.
215-
// "style" loader turns CSS into JS modules that inject <style> tags.
216-
// In production, we use a plugin to extract that CSS to a file, but
217-
// in development "style" loader enables hot editing of CSS.
218-
{
219-
test: /\.css$/,
220-
use: [
221-
require.resolve('style-loader'),
166+
// "oneOf" will traverse all following loaders until one will
167+
// match the requirements. When no loader matches it will fall
168+
// back to the "file" loader at the end of the loader list.
169+
oneOf: [
170+
// "url" loader works like "file" loader except that it embeds assets
171+
// smaller than specified limit in bytes as data URLs to avoid requests.
172+
// A missing `test` is equivalent to a match.
222173
{
223-
loader: require.resolve('css-loader'),
174+
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
175+
loader: require.resolve('url-loader'),
224176
options: {
225-
importLoaders: 1,
177+
limit: 10000,
178+
name: 'static/media/[name].[hash:8].[ext]',
226179
},
227180
},
181+
// Process JS with Babel.
182+
{
183+
test: /\.(js|jsx)$/,
184+
include: paths.appSrc,
185+
loader: require.resolve('babel-loader'),
186+
options: {
187+
// @remove-on-eject-begin
188+
babelrc: false,
189+
presets: [require.resolve('babel-preset-react-app')],
190+
// @remove-on-eject-end
191+
// This is a feature of `babel-loader` for webpack (not Babel itself).
192+
// It enables caching results in ./node_modules/.cache/babel-loader/
193+
// directory for faster rebuilds.
194+
cacheDirectory: true,
195+
},
196+
},
197+
// "postcss" loader applies autoprefixer to our CSS.
198+
// "css" loader resolves paths in CSS and adds assets as dependencies.
199+
// "style" loader turns CSS into JS modules that inject <style> tags.
200+
// In production, we use a plugin to extract that CSS to a file, but
201+
// in development "style" loader enables hot editing of CSS.
202+
{
203+
test: /\.css$/,
204+
use: [
205+
require.resolve('style-loader'),
206+
{
207+
loader: require.resolve('css-loader'),
208+
options: {
209+
importLoaders: 1,
210+
},
211+
},
212+
{
213+
loader: require.resolve('postcss-loader'),
214+
options: {
215+
// Necessary for external CSS imports to work
216+
// https://github.com/facebookincubator/create-react-app/issues/2677
217+
ident: 'postcss',
218+
plugins: () => [
219+
require('postcss-flexbugs-fixes'),
220+
autoprefixer({
221+
browsers: supportedBrowsers,
222+
flexbox: 'no-2009',
223+
}),
224+
],
225+
},
226+
},
227+
],
228+
},
229+
// "file" loader makes sure those assets get served by WebpackDevServer.
230+
// When you `import` an asset, you get its (virtual) filename.
231+
// In production, they would get copied to the `build` folder.
232+
// This loader don't uses a "test" so it will catch all modules
233+
// that fall through the other loaders.
228234
{
229-
loader: require.resolve('postcss-loader'),
235+
// Exclude `js` files to keep "css" loader working as it injects
236+
// it's runtime that would otherwise processed through "file" loader.
237+
// Also exclude `html` and `json` extensions so they get processed
238+
// by webpacks internal loaders.
239+
exclude: [/\.js$/, /\.html$/, /\.json$/],
240+
loader: require.resolve('file-loader'),
230241
options: {
231-
// Necessary for external CSS imports to work
232-
// https://github.com/facebookincubator/create-react-app/issues/2677
233-
ident: 'postcss',
234-
plugins: () => [
235-
require('postcss-flexbugs-fixes'),
236-
autoprefixer({
237-
supportedBrowsers,
238-
flexbox: 'no-2009',
239-
}),
240-
],
242+
name: 'static/media/[name].[hash:8].[ext]',
241243
},
242244
},
243245
],
244246
},
245247
// ** STOP ** Are you adding a new loader?
246-
// Remember to add the new extension(s) to the "file" loader exclusion list.
248+
// Make sure to add the new loader(s) before the "file" loader.
247249
],
248250
},
249251
plugins: [

packages/react-scripts/config/webpack.config.prod.js

+97-95
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ const getClientEnvironment = require('./env');
2727
let supportedBrowsers = require(paths.appPackageJson).browserslist;
2828
if (!supportedBrowsers || Object.keys(supportedBrowsers).length === 0) {
2929
// Assign default browsers when browserslist is not specified
30-
supportedBrowsers =
31-
"browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway]";
30+
supportedBrowsers = [
31+
'>1%',
32+
'last 4 versions',
33+
'Firefox ESR',
34+
'not ie < 9', // React doesn't support IE8 anyway
35+
];
3236
}
3337

3438
// Webpack uses `publicPath` to determine where the app is being served from.
@@ -160,104 +164,102 @@ module.exports = {
160164
],
161165
include: paths.appSrc,
162166
},
163-
// ** ADDING/UPDATING LOADERS **
164-
// The "file" loader handles all assets unless explicitly excluded.
165-
// The `exclude` list *must* be updated with every change to loader extensions.
166-
// When adding a new loader, you must add its `test`
167-
// as a new entry in the `exclude` list in the "file" loader.
168-
169-
// "file" loader makes sure those assets end up in the `build` folder.
170-
// When you `import` an asset, you get its filename.
171-
{
172-
exclude: [
173-
/\.html$/,
174-
/\.(js|jsx)$/,
175-
/\.css$/,
176-
/\.json$/,
177-
/\.bmp$/,
178-
/\.gif$/,
179-
/\.jpe?g$/,
180-
/\.png$/,
181-
],
182-
loader: require.resolve('file-loader'),
183-
options: {
184-
name: 'static/media/[name].[hash:8].[ext]',
185-
},
186-
},
187-
// "url" loader works just like "file" loader but it also embeds
188-
// assets smaller than specified size as data URLs to avoid requests.
189-
{
190-
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
191-
loader: require.resolve('url-loader'),
192-
options: {
193-
limit: 10000,
194-
name: 'static/media/[name].[hash:8].[ext]',
195-
},
196-
},
197-
// Process JS with Babel.
198-
{
199-
test: /\.(js|jsx)$/,
200-
include: paths.appSrc,
201-
loader: require.resolve('babel-loader'),
202-
options: {
203-
// @remove-on-eject-begin
204-
babelrc: false,
205-
presets: [require.resolve('babel-preset-react-app')],
206-
// @remove-on-eject-end
207-
compact: true,
208-
},
209-
},
210-
// The notation here is somewhat confusing.
211-
// "postcss" loader applies autoprefixer to our CSS.
212-
// "css" loader resolves paths in CSS and adds assets as dependencies.
213-
// "style" loader normally turns CSS into JS modules injecting <style>,
214-
// but unlike in development configuration, we do something different.
215-
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
216-
// (second argument), then grabs the result CSS and puts it into a
217-
// separate file in our build process. This way we actually ship
218-
// a single CSS file in production instead of JS code injecting <style>
219-
// tags. If you use code splitting, however, any async bundles will still
220-
// use the "style" loader inside the async code so CSS from them won't be
221-
// in the main CSS file.
222167
{
223-
test: /\.css$/,
224-
loader: ExtractTextPlugin.extract(
225-
Object.assign(
226-
{
227-
fallback: require.resolve('style-loader'),
228-
use: [
229-
{
230-
loader: require.resolve('css-loader'),
231-
options: {
232-
importLoaders: 1,
233-
minimize: true,
234-
sourceMap: true,
235-
},
236-
},
168+
// "oneOf" will traverse all following loaders until one will
169+
// match the requirements. When no loader matches it will fall
170+
// back to the "file" loader at the end of the loader list.
171+
oneOf: [
172+
// "url" loader works just like "file" loader but it also embeds
173+
// assets smaller than specified size as data URLs to avoid requests.
174+
{
175+
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
176+
loader: require.resolve('url-loader'),
177+
options: {
178+
limit: 10000,
179+
name: 'static/media/[name].[hash:8].[ext]',
180+
},
181+
},
182+
// Process JS with Babel.
183+
{
184+
test: /\.(js|jsx)$/,
185+
include: paths.appSrc,
186+
loader: require.resolve('babel-loader'),
187+
options: {
188+
// @remove-on-eject-begin
189+
babelrc: false,
190+
presets: [require.resolve('babel-preset-react-app')],
191+
// @remove-on-eject-end
192+
compact: true,
193+
},
194+
},
195+
// The notation here is somewhat confusing.
196+
// "postcss" loader applies autoprefixer to our CSS.
197+
// "css" loader resolves paths in CSS and adds assets as dependencies.
198+
// "style" loader normally turns CSS into JS modules injecting <style>,
199+
// but unlike in development configuration, we do something different.
200+
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
201+
// (second argument), then grabs the result CSS and puts it into a
202+
// separate file in our build process. This way we actually ship
203+
// a single CSS file in production instead of JS code injecting <style>
204+
// tags. If you use code splitting, however, any async bundles will still
205+
// use the "style" loader inside the async code so CSS from them won't be
206+
// in the main CSS file.
207+
{
208+
test: /\.css$/,
209+
loader: ExtractTextPlugin.extract(
210+
Object.assign(
237211
{
238-
loader: require.resolve('postcss-loader'),
239-
options: {
240-
// Necessary for external CSS imports to work
241-
// https://github.com/facebookincubator/create-react-app/issues/2677
242-
ident: 'postcss',
243-
plugins: () => [
244-
require('postcss-flexbugs-fixes'),
245-
autoprefixer({
246-
supportedBrowsers,
247-
flexbox: 'no-2009',
248-
}),
249-
],
250-
},
212+
fallback: require.resolve('style-loader'),
213+
use: [
214+
{
215+
loader: require.resolve('css-loader'),
216+
options: {
217+
importLoaders: 1,
218+
minimize: true,
219+
sourceMap: true,
220+
},
221+
},
222+
{
223+
loader: require.resolve('postcss-loader'),
224+
options: {
225+
// Necessary for external CSS imports to work
226+
// https://github.com/facebookincubator/create-react-app/issues/2677
227+
ident: 'postcss',
228+
plugins: () => [
229+
require('postcss-flexbugs-fixes'),
230+
autoprefixer({
231+
browsers: supportedBrowsers,
232+
flexbox: 'no-2009',
233+
}),
234+
],
235+
},
236+
},
237+
],
251238
},
252-
],
239+
extractTextPluginOptions
240+
)
241+
),
242+
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
243+
},
244+
// "file" loader makes sure assets end up in the `build` folder.
245+
// When you `import` an asset, you get its filename.
246+
// This loader don't uses a "test" so it will catch all modules
247+
// that fall through the other loaders.
248+
{
249+
loader: require.resolve('file-loader'),
250+
// Exclude `js` files to keep "css" loader working as it injects
251+
// it's runtime that would otherwise processed through "file" loader.
252+
// Also exclude `html` and `json` extensions so they get processed
253+
// by webpacks internal loaders.
254+
exclude: [/\.js$/, /\.html$/, /\.json$/],
255+
options: {
256+
name: 'static/media/[name].[hash:8].[ext]',
253257
},
254-
extractTextPluginOptions
255-
)
256-
),
257-
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
258+
},
259+
// ** STOP ** Are you adding a new loader?
260+
// Make sure to add the new loader(s) before the "file" loader.
261+
],
258262
},
259-
// ** STOP ** Are you adding a new loader?
260-
// Remember to add the new extension(s) to the "file" loader exclusion list.
261263
],
262264
},
263265
plugins: [

0 commit comments

Comments
 (0)