React Storybook无法显示SVG图标

6

我无法在Storybook中看到SVG图标。我是前端开发新手,不确定我的操作是否正确。我参考了这篇文章https://medium.com/@derek_19900/config-storybook-4-to-use-svgr-webpack-plugin-22cb1152f004。这是文件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;
};
3个回答

6

因为Storybook默认的webpack配置中已经有一个.svgloader并且正在使用file-loader,所以SVG无法在您的设置中加载到Storybook中。

请参见故事书base-webpack.config.js第65至68行

如果您想使用@svgr/webpackloader,则需要编写自定义webpack配置,以便在file-loader之前添加@svgr/webpack loader规则。

此webpack配置规则将在任何其他资源加载器之前添加@svgr/webpack loader:

  // 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],
  });

您可以在这个 Gatsby 起始模板(Gatsby + TypeScript + Emotion + Storybook)中看到完整的 webpack.config.js


1
我也看过你们官方博客对此的发布,但不知何故这仍然不起作用。 - Shai Kimchi
这个配置文件是从哪里来的?这个不起作用。 - Vikrant Bhat
你为什么要保留旧的svg assetLoader呢?为什么不只保留@svgr/webpack呢? - Nicu Surdu

3

使用 storybook-preset-inline-svg

Storybook已配置加载器,会与您在自定义Webpack配置中定义的内容发生冲突,因此如果不覆盖这些内容,则您的自定义规则将不起作用。

以下是覆盖一些默认SVG加载器的基本方法(根据您的需求进行调整):

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

根据您的设置,您可能需要查看 Webpack 的 Storybook 预设 API 来覆盖管理入口的加载器。

我尝试使用这段代码,但语法似乎不正确。对我来说它至少没有起作用(新规则的语法)。 - Antonio Gamiz Delgado
看起来少了一个右括号,并且map没有返回原始的非 SVG 规则。@AntonioGamizDelgado在我的编辑后可以再试一次,或者获取npm包。 - morganney
1
覆盖默认加载程序对我有用!我尝试了一些其他选项,这些选项更加明确或者尝试将 Storybook 默认配置与您自己的选项混合,但它们都会引发错误。虽然没有使用 storybook-preset-inline-svg,但在禁用 Storybook 规则后,只是使用了我的项目自己的解决方案,这样做起来非常顺畅。 - Orion Hall

1
在最新的故事书中,这是解决方案: 将您的脚本设置为 package.json
"scripts": {
  "storybook": "start-storybook -p 6006 --no-dll -s ./public",
}

不要使用storybook 6.3.0 =( - Andrey Patseiko
6.4.14 中也不起作用。 - Hafiz Temuri
1
在6.4.19中也不起作用。 - James Pearson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接