Config Storybook 4 & 5 to use SVGR webpack plugin

Update: This still works with Storybook 5, however webpack config setup is a little different. In webpack.config.js , instead of module.export = (_, _, config) => { ... } , it should be module.export = ({ config }) => { ... } .

SVGR turns your .svg into React components. It also has a webpack loader that’ll allow you to import .svg directly into your javascript file.

That’s really neat. Except if you want to use it with Storybook, this happens:

⚠️ Failed to execute ‘createElement’ on ‘Document’: The tag name provided (‘static/media/your-svg-24.9924d06f.svg’) is not a valid name.

If you’re using create-react-app 2 with storybook 4, you’re actually set — SVGR is shipped with CRA2, and latest version of Storybook supports CRA2 out of the box. Try upgrading storybook if you see the same error message.

If you plant and grow your own webpack config, however, this is what went wrong: Storybook’s default webpack config already has a .svg loader.

{ 
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
loader: 'file-loader',
query: { name: 'static/media/[name].[hash:8].[ext]' }
},

You can search for the file loader rule in storybook’s default webpack config by testing each rule’s regex test, then add an exclusion rule to it:

const fileLoaderRule = defaultConfig.module.rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = pathToYourInlineSvg
Full sample code

That’s all! Since all my .svg icons are exported to a folder ( pathToInlineSvg), I choose to exclude a directory; but you can easily exclude based on extension name, i.e my-icon.inline.svg or something similar.