Skip to content

Commit 4324ef1

Browse files
iansuyoiang
authored andcommitted
Import SVGs as React components (#1388) (#3718)
* Import SVGs as React components (#1388) * Updated webpack production config and fixed tests * Improved Jest SVG file transform * Improved SVG tests * Add a comment * Update webpack.config.prod.js # Conflicts: # packages/react-scripts/package.json
1 parent 55bdf73 commit 4324ef1

File tree

6 files changed

+92
-2
lines changed

6 files changed

+92
-2
lines changed

packages/react-scripts/config/jest/fileTransform.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ const path = require('path');
1515

1616
module.exports = {
1717
process(src, filename) {
18-
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
18+
const assetFilename = JSON.stringify(path.basename(filename));
19+
20+
if (filename.match(/\.svg$/)) {
21+
return `module.exports = {
22+
__esModule: true,
23+
default: ${assetFilename},
24+
ReactComponent: () => ${assetFilename},
25+
};`;
26+
}
27+
28+
return `module.exports = ${assetFilename};`;
1929
},
2030
};

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

+25
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,31 @@ module.exports = {
220220
},
221221
],
222222
},
223+
// Allows you to use two kinds of imports for SVG:
224+
// import logoUrl from './logo.svg'; gives you the URL.
225+
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
226+
{
227+
test: /\.svg$/,
228+
use: [
229+
{
230+
loader: require.resolve('babel-loader'),
231+
options: {
232+
// @remove-on-eject-begin
233+
babelrc: false,
234+
presets: [require.resolve('babel-preset-react-app')],
235+
// @remove-on-eject-end
236+
cacheDirectory: true,
237+
},
238+
},
239+
require.resolve('svgr/webpack'),
240+
{
241+
loader: require.resolve('file-loader'),
242+
options: {
243+
name: 'static/media/[name].[hash:8].[ext]',
244+
},
245+
},
246+
],
247+
},
223248
// "file" loader makes sure those assets get served by WebpackDevServer.
224249
// When you `import` an asset, you get its (virtual) filename.
225250
// In production, they would get copied to the `build` folder.

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

+25
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,31 @@ module.exports = {
246246
),
247247
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
248248
},
249+
// Allows you to use two kinds of imports for SVG:
250+
// import logoUrl from './logo.svg'; gives you the URL.
251+
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
252+
{
253+
test: /\.svg$/,
254+
use: [
255+
{
256+
loader: require.resolve('babel-loader'),
257+
options: {
258+
// @remove-on-eject-begin
259+
babelrc: false,
260+
presets: [require.resolve('babel-preset-react-app')],
261+
// @remove-on-eject-end
262+
cacheDirectory: true,
263+
},
264+
},
265+
require.resolve('svgr/webpack'),
266+
{
267+
loader: require.resolve('file-loader'),
268+
options: {
269+
name: 'static/media/[name].[hash:8].[ext]',
270+
},
271+
},
272+
],
273+
},
249274
// "file" loader makes sure assets end up in the `build` folder.
250275
// When you `import` an asset, you get its filename.
251276
// This loader doesn't use a "test" so it will catch all modules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import { ReactComponent as Logo } from './assets/logo.svg';
10+
11+
export default () => <Logo />;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import ReactDOM from 'react-dom';
10+
import SvgComponent from './SvgComponent';
11+
12+
describe('svg component', () => {
13+
it('renders without crashing', () => {
14+
const div = document.createElement('div');
15+
ReactDOM.render(<SvgComponent />, div);
16+
expect(div.textContent).toBe('logo.svg');
17+
});
18+
});

packages/react-scripts/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
"source-map-loader": "^0.2.1",
4545
"react-dev-utils": "^5.0.1",
4646
"resolve": "1.6.0",
47-
"style-loader": "0.19.0",
47+
"style-loader": "0.19.1",
48+
"svgr": "1.6.0",
4849
"sw-precache-webpack-plugin": "0.11.4",
4950
"ts-jest": "22.0.1",
5051
"ts-loader": "^2.3.7",

0 commit comments

Comments
 (0)