Skip to content

Commit 2d4fbe3

Browse files
Furizaaswengorschewski
authored andcommitted
Use Rule.oneOf to resolve correct loader (#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 0242f91 commit 2d4fbe3

File tree

2 files changed

+155
-167
lines changed

2 files changed

+155
-167
lines changed

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

+67-73
Original file line numberDiff line numberDiff line change
@@ -151,91 +151,85 @@ module.exports = {
151151
enforce: 'pre',
152152
include: paths.appSrc,
153153
},
154-
// ** ADDING/UPDATING LOADERS **
155-
// The "file" loader handles all assets unless explicitly excluded.
156-
// The `exclude` list *must* be updated with every change to loader extensions.
157-
// When adding a new loader, you must add its `test`
158-
// as a new entry in the `exclude` list for "file" loader.
159-
160-
// "file" loader makes sure those assets get served by WebpackDevServer.
161-
// When you `import` an asset, you get its (virtual) filename.
162-
// In production, they would get copied to the `build` folder.
163-
{
164-
exclude: [
165-
/\.html$/,
166-
/\.(js|jsx)$/,
167-
/\.(ts|tsx)$/,
168-
/\.css$/,
169-
/\.json$/,
170-
/\.bmp$/,
171-
/\.gif$/,
172-
/\.jpe?g$/,
173-
/\.png$/,
174-
],
175-
loader: require.resolve('file-loader'),
176-
options: {
177-
name: 'static/media/[name].[hash:8].[ext]',
178-
},
179-
},
180-
// "url" loader works like "file" loader except that it embeds assets
181-
// smaller than specified limit in bytes as data URLs to avoid requests.
182-
// A missing `test` is equivalent to a match.
183-
{
184-
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
185-
loader: require.resolve('url-loader'),
186-
options: {
187-
limit: 10000,
188-
name: 'static/media/[name].[hash:8].[ext]',
189-
},
190-
},
191-
// Compile .tsx?
192-
{
193-
test: /\.(ts|tsx)$/,
194-
include: paths.appSrc,
195-
loader: require.resolve('ts-loader'),
196-
options: {
197-
configFileName: 'tsconfig.react.json',
198-
},
199-
},
200-
// "postcss" loader applies autoprefixer to our CSS.
201-
// "css" loader resolves paths in CSS and adds assets as dependencies.
202-
// "style" loader turns CSS into JS modules that inject <style> tags.
203-
// In production, we use a plugin to extract that CSS to a file, but
204-
// in development "style" loader enables hot editing of CSS.
205154
{
206-
test: /\.css$/,
207-
use: [
208-
require.resolve('style-loader'),
155+
// "oneOf" will traverse all following loaders until one will
156+
// match the requirements. When no loader matches it will fall
157+
// back to the "file" loader at the end of the loader list.
158+
oneOf: [
159+
// "url" loader works like "file" loader except that it embeds assets
160+
// smaller than specified limit in bytes as data URLs to avoid requests.
161+
// A missing `test` is equivalent to a match.
209162
{
210-
loader: require.resolve('css-loader'),
163+
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
164+
loader: require.resolve('url-loader'),
211165
options: {
212-
importLoaders: 1,
166+
limit: 10000,
167+
name: 'static/media/[name].[hash:8].[ext]',
213168
},
214169
},
170+
// Compile .tsx?
215171
{
216-
loader: require.resolve('postcss-loader'),
217-
options: {
218-
// Necessary for external CSS imports to work
219-
// https://github.com/facebookincubator/create-react-app/issues/2677
220-
ident: 'postcss',
221-
plugins: () => [
222-
require('postcss-flexbugs-fixes'),
223-
autoprefixer({
224-
browsers: [
225-
'>1%',
226-
'last 4 versions',
227-
'Firefox ESR',
228-
'not ie < 9', // React doesn't support IE8 anyway
172+
test: /\.(ts|tsx)$/,
173+
include: paths.appSrc,
174+
loader: require.resolve('ts-loader'),
175+
},
176+
// "postcss" loader applies autoprefixer to our CSS.
177+
// "css" loader resolves paths in CSS and adds assets as dependencies.
178+
// "style" loader turns CSS into JS modules that inject <style> tags.
179+
// In production, we use a plugin to extract that CSS to a file, but
180+
// in development "style" loader enables hot editing of CSS.
181+
{
182+
test: /\.css$/,
183+
use: [
184+
require.resolve('style-loader'),
185+
{
186+
loader: require.resolve('css-loader'),
187+
options: {
188+
importLoaders: 1,
189+
},
190+
},
191+
{
192+
loader: require.resolve('postcss-loader'),
193+
options: {
194+
// Necessary for external CSS imports to work
195+
// https://github.com/facebookincubator/create-react-app/issues/2677
196+
ident: 'postcss',
197+
plugins: () => [
198+
require('postcss-flexbugs-fixes'),
199+
autoprefixer({
200+
browsers: [
201+
'>1%',
202+
'last 4 versions',
203+
'Firefox ESR',
204+
'not ie < 9', // React doesn't support IE8 anyway
205+
],
206+
flexbox: 'no-2009',
207+
}),
229208
],
230-
flexbox: 'no-2009',
231-
}),
232-
],
209+
},
210+
},
211+
],
212+
},
213+
// "file" loader makes sure those assets get served by WebpackDevServer.
214+
// When you `import` an asset, you get its (virtual) filename.
215+
// In production, they would get copied to the `build` folder.
216+
// This loader don't uses a "test" so it will catch all modules
217+
// that fall through the other loaders.
218+
{
219+
// Exclude `js` files to keep "css" loader working as it injects
220+
// it's runtime that would otherwise processed through "file" loader.
221+
// Also exclude `html` and `json` extensions so they get processed
222+
// by webpacks internal loaders.
223+
exclude: [/\.js$/, /\.html$/, /\.json$/],
224+
loader: require.resolve('file-loader'),
225+
options: {
226+
name: 'static/media/[name].[hash:8].[ext]',
233227
},
234228
},
235229
],
236230
},
237231
// ** STOP ** Are you adding a new loader?
238-
// Remember to add the new extension(s) to the "file" loader exclusion list.
232+
// Make sure to add the new loader(s) before the "file" loader.
239233
],
240234
},
241235
plugins: [

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

+88-94
Original file line numberDiff line numberDiff line change
@@ -151,106 +151,100 @@ module.exports = {
151151
enforce: 'pre',
152152
include: paths.appSrc,
153153
},
154-
// ** ADDING/UPDATING LOADERS **
155-
// The "file" loader handles all assets unless explicitly excluded.
156-
// The `exclude` list *must* be updated with every change to loader extensions.
157-
// When adding a new loader, you must add its `test`
158-
// as a new entry in the `exclude` list in the "file" loader.
159-
160-
// "file" loader makes sure those assets end up in the `build` folder.
161-
// When you `import` an asset, you get its filename.
162-
{
163-
exclude: [
164-
/\.html$/,
165-
/\.(js|jsx)$/,
166-
/\.(ts|tsx)$/,
167-
/\.css$/,
168-
/\.json$/,
169-
/\.bmp$/,
170-
/\.gif$/,
171-
/\.jpe?g$/,
172-
/\.png$/,
173-
],
174-
loader: require.resolve('file-loader'),
175-
options: {
176-
name: 'static/media/[name].[hash:8].[ext]',
177-
},
178-
},
179-
// "url" loader works just like "file" loader but it also embeds
180-
// assets smaller than specified size as data URLs to avoid requests.
181-
{
182-
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
183-
loader: require.resolve('url-loader'),
184-
options: {
185-
limit: 10000,
186-
name: 'static/media/[name].[hash:8].[ext]',
187-
},
188-
},
189-
// Compile .tsx?
190-
{
191-
test: /\.(ts|tsx)$/,
192-
include: paths.appSrc,
193-
loader: require.resolve('ts-loader'),
194-
options: {
195-
configFileName: 'tsconfig.react.json',
196-
},
197-
},
198-
// The notation here is somewhat confusing.
199-
// "postcss" loader applies autoprefixer to our CSS.
200-
// "css" loader resolves paths in CSS and adds assets as dependencies.
201-
// "style" loader normally turns CSS into JS modules injecting <style>,
202-
// but unlike in development configuration, we do something different.
203-
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
204-
// (second argument), then grabs the result CSS and puts it into a
205-
// separate file in our build process. This way we actually ship
206-
// a single CSS file in production instead of JS code injecting <style>
207-
// tags. If you use code splitting, however, any async bundles will still
208-
// use the "style" loader inside the async code so CSS from them won't be
209-
// in the main CSS file.
210154
{
211-
test: /\.css$/,
212-
loader: ExtractTextPlugin.extract(
213-
Object.assign(
214-
{
215-
fallback: require.resolve('style-loader'),
216-
use: [
217-
{
218-
loader: require.resolve('css-loader'),
219-
options: {
220-
importLoaders: 1,
221-
minimize: true,
222-
sourceMap: true,
223-
},
224-
},
155+
// "oneOf" will traverse all following loaders until one will
156+
// match the requirements. When no loader matches it will fall
157+
// back to the "file" loader at the end of the loader list.
158+
oneOf: [
159+
// "url" loader works just like "file" loader but it also embeds
160+
// assets smaller than specified size as data URLs to avoid requests.
161+
{
162+
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
163+
loader: require.resolve('url-loader'),
164+
options: {
165+
limit: 10000,
166+
name: 'static/media/[name].[hash:8].[ext]',
167+
},
168+
},
169+
//Compile .tsx?
170+
{
171+
test: /\.(ts|tsx)$/,
172+
include: paths.appSrc,
173+
loader: require.resolve('ts-loader')
174+
},
175+
// The notation here is somewhat confusing.
176+
// "postcss" loader applies autoprefixer to our CSS.
177+
// "css" loader resolves paths in CSS and adds assets as dependencies.
178+
// "style" loader normally turns CSS into JS modules injecting <style>,
179+
// but unlike in development configuration, we do something different.
180+
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
181+
// (second argument), then grabs the result CSS and puts it into a
182+
// separate file in our build process. This way we actually ship
183+
// a single CSS file in production instead of JS code injecting <style>
184+
// tags. If you use code splitting, however, any async bundles will still
185+
// use the "style" loader inside the async code so CSS from them won't be
186+
// in the main CSS file.
187+
{
188+
test: /\.css$/,
189+
loader: ExtractTextPlugin.extract(
190+
Object.assign(
225191
{
226-
loader: require.resolve('postcss-loader'),
227-
options: {
228-
// Necessary for external CSS imports to work
229-
// https://github.com/facebookincubator/create-react-app/issues/2677
230-
ident: 'postcss',
231-
plugins: () => [
232-
require('postcss-flexbugs-fixes'),
233-
autoprefixer({
234-
browsers: [
235-
'>1%',
236-
'last 4 versions',
237-
'Firefox ESR',
238-
'not ie < 9', // React doesn't support IE8 anyway
192+
fallback: require.resolve('style-loader'),
193+
use: [
194+
{
195+
loader: require.resolve('css-loader'),
196+
options: {
197+
importLoaders: 1,
198+
minimize: true,
199+
sourceMap: true,
200+
},
201+
},
202+
{
203+
loader: require.resolve('postcss-loader'),
204+
options: {
205+
// Necessary for external CSS imports to work
206+
// https://github.com/facebookincubator/create-react-app/issues/2677
207+
ident: 'postcss',
208+
plugins: () => [
209+
require('postcss-flexbugs-fixes'),
210+
autoprefixer({
211+
browsers: [
212+
'>1%',
213+
'last 4 versions',
214+
'Firefox ESR',
215+
'not ie < 9', // React doesn't support IE8 anyway
216+
],
217+
flexbox: 'no-2009',
218+
}),
239219
],
240-
flexbox: 'no-2009',
241-
}),
242-
],
243-
},
220+
},
221+
},
222+
],
244223
},
245-
],
224+
extractTextPluginOptions
225+
)
226+
),
227+
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
228+
},
229+
// "file" loader makes sure assets end up in the `build` folder.
230+
// When you `import` an asset, you get its filename.
231+
// This loader don't uses a "test" so it will catch all modules
232+
// that fall through the other loaders.
233+
{
234+
loader: require.resolve('file-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+
options: {
241+
name: 'static/media/[name].[hash:8].[ext]',
246242
},
247-
extractTextPluginOptions
248-
)
249-
),
250-
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
243+
},
244+
// ** STOP ** Are you adding a new loader?
245+
// Make sure to add the new loader(s) before the "file" loader.
246+
],
251247
},
252-
// ** STOP ** Are you adding a new loader?
253-
// Remember to add the new extension(s) to the "file" loader exclusion list.
254248
],
255249
},
256250
plugins: [

0 commit comments

Comments
 (0)