Skip to content

Commit b48e3d2

Browse files
pugnascotiaTimer
authored andcommitted
Whitelist files that can be embedded through url-loader (facebook#1305)
* Whitelist files that can be embedded through url-loader Change the current catch-all loader to use file-loader instead of url-loader, and exclude common image file extensons. Add another url-loader for images, configured identically to the original catch-all loader. Part of issue facebook#1293. * Update tests to reflect change in loader config * Integration test fix * More CI fixes * Work around broken loader-utils behaviour in integration tests * Revise the documentation around file loading * Documentation tweaks * Docs tweak * Update test now that webpack/loader-utils has been updated * Update react-scripts to depend on babel-loader@7.0.0-alpha.2 * Bump deps
1 parent 558bf20 commit b48e3d2

File tree

7 files changed

+56
-35
lines changed

7 files changed

+56
-35
lines changed

config/webpack.config.dev.js

+22-11
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,34 @@ module.exports = {
134134
// When adding a new loader, you must add its `test`
135135
// as a new entry in the `exclude` list for "url" loader.
136136

137-
// "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
138-
// Otherwise, it acts like the "file" loader.
137+
// "file" loader makes sure those assets get served by WebpackDevServer.
138+
// When you `import` an asset, you get its (virtual) filename.
139+
// In production, they would get copied to the `build` folder.
139140
{
140141
exclude: [
141142
/\.html$/,
142143
/\.(js|jsx)$/,
143144
/\.css$/,
144145
/\.json$/,
145-
/\.svg$/
146+
/\.bmp$/,
147+
/\.gif$/,
148+
/\.jpe?g$/,
149+
/\.png$/
150+
],
151+
loader: 'file-loader',
152+
options: {
153+
name: 'static/media/[name].[hash:8].[ext]'
154+
}
155+
},
156+
// "url" loader works like "file" loader except that it embeds assets
157+
// smaller than specified limit in bytes as data URLs to avoid requests.
158+
// A missing `test` is equivalent to a match.
159+
{
160+
test: [
161+
/\.bmp$/,
162+
/\.gif$/,
163+
/\.jpe?g$/,
164+
/\.png$/
146165
],
147166
loader: 'url-loader',
148167
options: {
@@ -198,14 +217,6 @@ module.exports = {
198217
}
199218
}
200219
]
201-
},
202-
// "file" loader for svg
203-
{
204-
test: /\.svg$/,
205-
loader: 'file-loader',
206-
options: {
207-
name: 'static/media/[name].[hash:8].[ext]'
208-
}
209220
}
210221
// ** STOP ** Are you adding a new loader?
211222
// Remember to add the new extension(s) to the "url" loader exclusion list.

config/webpack.config.prod.js

+20-11
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,32 @@ module.exports = {
138138
// When adding a new loader, you must add its `test`
139139
// as a new entry in the `exclude` list in the "url" loader.
140140

141-
// "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
142-
// Otherwise, it acts like the "file" loader.
141+
// "file" loader makes sure those assets end up in the `build` folder.
142+
// When you `import` an asset, you get its filename.
143143
{
144144
exclude: [
145145
/\.html$/,
146146
/\.(js|jsx)$/,
147147
/\.css$/,
148148
/\.json$/,
149-
/\.svg$/
149+
/\.bmp$/,
150+
/\.gif$/,
151+
/\.jpe?g$/,
152+
/\.png$/
153+
],
154+
loader: 'file-loader',
155+
options: {
156+
name: 'static/media/[name].[hash:8].[ext]'
157+
}
158+
},
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: [
163+
/\.bmp$/,
164+
/\.gif$/,
165+
/\.jpe?g$/,
166+
/\.png$/
150167
],
151168
loader: 'url-loader',
152169
options: {
@@ -209,14 +226,6 @@ module.exports = {
209226
]
210227
}, extractTextPluginOptions))
211228
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
212-
},
213-
// "file" loader for svg
214-
{
215-
test: /\.svg$/,
216-
loader: 'file-loader',
217-
options: {
218-
name: 'static/media/[name].[hash:8].[ext]'
219-
}
220229
}
221230
// ** STOP ** Are you adding a new loader?
222231
// Remember to add the new extension(s) to the "url" loader exclusion list.

fixtures/kitchensink/integration/webpack.test.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ describe('Integration', () => {
2828
it('no ext inclusion', async () => {
2929
const doc = await initDOM('no-ext-inclusion')
3030

31-
expect(doc.getElementById('feature-no-ext-inclusion').textContent)
32-
.to.equal('This is just a file without an extension.')
31+
expect(doc.getElementById('feature-no-ext-inclusion').href).to.match(/\/static\/media\/aFileWithoutExt\.[a-f0-9]{8}\.bin$/)
3332
})
3433

3534
it('json inclusion', async () => {
@@ -47,7 +46,7 @@ describe('Integration', () => {
4746
it('unknown ext inclusion', async () => {
4847
const doc = await initDOM('unknown-ext-inclusion')
4948

50-
expect(doc.getElementById('feature-unknown-ext-inclusion').textContent).to.equal('Whoooo, spooky!.')
49+
expect(doc.getElementById('feature-unknown-ext-inclusion').href).to.match(/\/static\/media\/aFileWithExt\.[a-f0-9]{8}\.unknown$/)
5150
})
5251
})
5352
})

fixtures/kitchensink/src/features/webpack/NoExtInclusion.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ const text = aFileWithoutExt.includes('base64')
1515
: aFileWithoutExt
1616

1717
export default () => (
18-
<p id="feature-no-ext-inclusion">{text}.</p>
18+
<a id="feature-no-ext-inclusion" href={text}>aFileWithoutExt</a>
1919
)

fixtures/kitchensink/src/features/webpack/UnknownExtInclusion.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ const text = aFileWithExtUnknown.includes('base64')
1515
: aFileWithExtUnknown
1616

1717
export default () => (
18-
<p id="feature-unknown-ext-inclusion">{text}.</p>
18+
<a id="feature-unknown-ext-inclusion" href={text}>aFileWithExtUnknown</a>
1919
)

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
"babel-core": "6.23.1",
2828
"babel-eslint": "7.1.1",
2929
"babel-jest": "18.0.0",
30-
"babel-loader": "6.3.2",
30+
"babel-loader": "7.0.0-alpha.3",
3131
"babel-preset-react-app": "^2.1.1",
3232
"babel-runtime": "^6.20.0",
3333
"case-sensitive-paths-webpack-plugin": "1.1.4",
3434
"chalk": "1.1.3",
3535
"connect-history-api-fallback": "1.3.0",
3636
"cross-spawn": "4.0.2",
37-
"css-loader": "0.26.1",
37+
"css-loader": "0.26.2",
3838
"detect-port": "1.0.1",
3939
"dotenv": "2.0.0",
4040
"eslint": "3.16.1",
@@ -45,16 +45,16 @@
4545
"eslint-plugin-jsx-a11y": "4.0.0",
4646
"eslint-plugin-react": "6.4.1",
4747
"extract-text-webpack-plugin": "2.0.0",
48-
"file-loader": "0.10.0",
48+
"file-loader": "0.10.1",
4949
"fs-extra": "0.30.0",
5050
"html-webpack-plugin": "2.28.0",
5151
"http-proxy-middleware": "0.17.3",
5252
"jest": "18.1.0",
5353
"object-assign": "4.1.1",
54-
"postcss-loader": "1.3.1",
54+
"postcss-loader": "1.3.3",
5555
"promise": "7.1.1",
5656
"react-dev-utils": "^0.5.2",
57-
"style-loader": "0.13.1",
57+
"style-loader": "0.13.2",
5858
"url-loader": "0.5.7",
5959
"webpack": "2.2.1",
6060
"webpack-dev-server": "2.4.1",

template/README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ You can find the most recent version of this guide [here](https://github.com/fac
2323
- [Adding a Stylesheet](#adding-a-stylesheet)
2424
- [Post-Processing CSS](#post-processing-css)
2525
- [Adding a CSS Preprocessor (Sass, Less etc.)](#adding-a-css-preprocessor-sass-less-etc)
26-
- [Adding Images and Fonts](#adding-images-and-fonts)
26+
- [Adding Images, Fonts, and Files](#adding-images-fonts-and-files)
2727
- [Using the `public` Folder](#using-the-public-folder)
2828
- [Changing the HTML](#changing-the-html)
2929
- [Adding Assets Outside of the Module System](#adding-assets-outside-of-the-module-system)
@@ -466,11 +466,13 @@ Then we can change `start` and `build` scripts to include the CSS preprocessor c
466466

467467
Now running `npm start` and `npm run build` also builds Sass files. Note that `node-sass` seems to have an [issue recognizing newly created files on some systems](https://github.com/sass/node-sass/issues/1891) so you might need to restart the watcher when you create a file until it’s resolved.
468468

469-
## Adding Images and Fonts
469+
## Adding Images, Fonts, and Files
470470

471471
With Webpack, using static assets like images and fonts works similarly to CSS.
472472

473-
You can **`import` an image right in a JavaScript module**. This tells Webpack to include that image in the bundle. Unlike CSS imports, importing an image or a font gives you a string value. This value is the final image path you can reference in your code.
473+
You can **`import` a file right in a JavaScript module**. This tells Webpack to include that file in the bundle. Unlike CSS imports, importing a file gives you a string value. This value is the final path you can reference in your code, e.g. as the `src` attribute of an image or the `href` of a link to a PDF.
474+
475+
To reduce the number of requests to the server, importing images that are less than 10,000 bytes returns a [data URI](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) instead of a path. This applies to the following file extensions: bmp, gif, jpg, jpeg, and png. SVG files are excluded due to [#1153](https://github.com/facebookincubator/create-react-app/issues/1153).
474476

475477
Here is an example:
476478

0 commit comments

Comments
 (0)