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 4 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
4 changes: 4 additions & 0 deletions packages/react-scripts/config/jest/fileTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const path = require('path');

module.exports = {
process(src, filename) {
if (filename.match(/\.svg$/)) {
return `module.exports = {ReactComponent: () => ('')};`;
Copy link
Contributor

Choose a reason for hiding this comment

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

If we don’t want to render anything can this just return null?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is not quite accurate. There should be two exports: default and named one. Tests that expect this to render to the filename shouldn’t start failing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't exactly sure what to return there. Null would probably work. Also wasn't sure about the exports. How do you return a default and named export using 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.

Maybe something like

module.exports = {
  __esModule: true,
  default: name,
  ReactComponent: () => name
}

}

return `module.exports = ${JSON.stringify(path.basename(filename))};`;
},
};
22 changes: 22 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,28 @@ 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?

{
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
22 changes: 22 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,28 @@ module.exports = {
),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
{
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,17 @@
/**
* 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.

});
});
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