Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import SVGs as React components (#1388) #3718

Merged
merged 8 commits into from
Jan 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/react-scripts/config/jest/fileTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ const path = require('path');

module.exports = {
process(src, filename) {
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
const assetFilename = JSON.stringify(path.basename(filename));

if (filename.match(/\.svg$/)) {
return `module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: () => ${assetFilename},
};`;
}

return `module.exports = ${assetFilename};`;
},
};
25 changes: 25 additions & 0 deletions packages/react-scripts/config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,31 @@ module.exports = {
},
],
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need a change in production config too?

// Allows you to use two kinds of imports for SVG:
// import logoUrl from './logo.svg'; gives you the URL.
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
{
test: /\.svg$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
// @remove-on-eject-begin
babelrc: false,
presets: [require.resolve('babel-preset-react-app')],
// @remove-on-eject-end
cacheDirectory: true,
},
},
require.resolve('svgr/webpack'),
{
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
Expand Down
25 changes: 25 additions & 0 deletions packages/react-scripts/config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,31 @@ module.exports = {
),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
// Allows you to use two kinds of imports for SVG:
// import logoUrl from './logo.svg'; gives you the URL.
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
{
test: /\.svg$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
// @remove-on-eject-begin
babelrc: false,
presets: [require.resolve('babel-preset-react-app')],
// @remove-on-eject-end
cacheDirectory: true,
},
},
require.resolve('svgr/webpack'),
{
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
// "file" loader makes sure assets end up in the `build` folder.
// When you `import` an asset, you get its filename.
// This loader doesn't use a "test" so it will catch all modules
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { ReactComponent as Logo } from './assets/logo.svg';

export default () => <Logo />;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import SvgComponent from './SvgComponent';

describe('svg component', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<SvgComponent />, div);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And in this test you could verify the div.textContent matches the filename.

expect(div.textContent).toBe('logo.svg');
});
});
1 change: 1 addition & 0 deletions packages/react-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"raf": "3.4.0",
"react-dev-utils": "^5.0.0",
"style-loader": "0.19.1",
"svgr": "1.6.0",
"sw-precache-webpack-plugin": "0.11.4",
"thread-loader": "1.1.2",
"uglifyjs-webpack-plugin": "1.1.6",
Expand Down