React Storybook SVG Failed to execute 'createElement' on 'Document'

Mark Robson picture Mark Robson · Jan 21, 2019 · Viewed 8.9k times · Source

I'm trying to add Storybook to an existing React app but getting errors with imported svg files. The svg is imported and used like:

import Border from './images/border.inline.svg'
...
<Border className="card__border" />

This works when the app is run and built, but I get an error in Storybook. How come?


Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/border.inline.258eb86a.svg') is not a valid name.
Error: Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/border.inline.258eb86a.svg') is not a valid name.

The default webpack.config.js has:

  ...
  {
    test: /\.inline.svg$/,
    loader: 'svg-react-loader'
  },
  ...

Also, the existing code uses webpack 3, and I'm using Storybook V4.

Answer

Derek Nguyen picture Derek Nguyen · Jan 21, 2019

This is happening because Storybook's default webpack config has its own svg config:

{ 
  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]' }
},

I'm pretty sure this is the cause, because you can see the path outlined in error message: query: { name: 'static/media/[name].[hash:8].[ext]' } -> static/media/border.inline.258eb86a.svg

The solution can be to find the existing loader & change / or add an exclude rule to it. Here's an example of a custom .storybook/webpack.config.js:

// storybook 4
module.exports = (_, _, config) => {
// storybook 5
module.exports = ({ config }) => {
  const rules = config.module.rules;

  // modify storybook's file-loader rule to avoid conflicts with your inline svg
  const fileLoaderRule = rules.find(rule => rule.test.test('.svg'));
  fileLoaderRule.exclude = /\.inline.svg$/;

  rules.push({
    test: /\.inline.svg$/,
    ...
    }],
  });

  return config;
};