NewQueries
NewQueries

Reputation: 4931

React Storybook not displaying SVG icons

I am not able to see the SVG icons in Storybook. I am new to front-end development so not sure what I am doing wrong. I referred to this article https://medium.com/@derek_19900/config-storybook-4-to-use-svgr-webpack-plugin-22cb1152f004. Here is file webpack.config.js

const path = require('path');

const rootDir = path.resolve(__dirname, '../src');

const pathToInlineSvg = path.resolve(__dirname, '../src/assets/images/icons');

module.exports = ({ config, mode }) => {

  const fileLoaderRule = config.module.rules.find(rule => rule.test.test('.svg'));
  fileLoaderRule.exclude = pathToInlineSvg;

  config.module.rules = config.module.rules.map(rule => {
    if (rule.exclude && rule.test.test('styles.scss')) {
      rule.use = rule.use.map(use => {
        if (use && use.loader && use.loader.indexOf('sass-loader') !== -1) {
          use.options.data = `
            @import "@/assets/styles/theme.scss";
            @import "@/assets/styles/fonts.scss";
          `;
        }
        return use;
      });
    }
    return rule;
  });

  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
      presets: [['react-app', { flow: false, typescript: true }]],
    },
  });

  config.module.rules.push({
    test: /\.(jsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
      presets: ["@babel/preset-env", "@salesforce/babel-preset-design-system-react"],
    },
  });

  config.module.rules.push({
    test: /\.svg$/,
    include: pathToInlineSvg,
    use: [{loader: '@svgr/webpack',
              options: {
                icon: true,
              },
          }
    ],
  });

  config.resolve.extensions.push('.ts', '.tsx', '.svg');
  config.resolve.alias['@'] = rootDir;

  return config;
};

Upvotes: 7

Views: 22376

Answers (3)

morganney
morganney

Reputation: 13580

Use storybook-preset-inline-svg.

Storybook has loaders configured that conflict with what you define in your custom Webpack configuration, so if you do not override those then your custom rules will not work.

Here's a basic way to override some of the default SVG loaders (adjust to your needs):

config.module.rules = [
  ...config.module.rules.map(rule => {
    if (/svg/.test(rule.test)) {
      // Silence the Storybook loaders for SVG files
      return { ...rule, exclude: /\.svg$/i }
    }

    return rule
  }),
  // Add your custom SVG loader
  {
    test: /\.svg$/i,
    use: ['whatever-loader-you-want']
  }
]

Depending on your setup you may want to look into the Storybook preset API for Webpack to override loaders for the manager entries too.

Upvotes: 4

Esteban Dalel R
Esteban Dalel R

Reputation: 43

In the newest storybook here's the solution: Set your script on package.json to

"scripts": {
  "storybook": "start-storybook -p 6006 --no-dll -s ./public",
}

Upvotes: 0

Duncan
Duncan

Reputation: 149

SVGs are not loading into Storybook in your setup because Storybook’s default webpack config already has a .svg loader, and is using file-loader.

See Line 65 - Line 68 of Storybook base-webpack.config.js

If you want to use @svgr/webpack loader, you need to write a custom webpack config so that the @svgr/webpack loader rule is before the file-loader.

This webpack config rule adds the @svgr/webpack loader before any other asset loaders:

  // Add SVGR Loader
  // ========================================================
  // Remove svg rules from existing webpack rule
  const assetRule = config.module.rules.find(({ test }) => test.test('.svg'));

  const assetLoader = {
    loader: assetRule.loader,
    options: assetRule.options || assetRule.query,
  };

  config.module.rules.unshift({
    test: /\.svg$/,
    use: ['@svgr/webpack', assetLoader],
  });

You can see a complete webpack.config.js in this Gatsby starter (Gatsby + TypeScript + Emotion + Storybook)

Upvotes: 7

Related Questions