【问题标题】:React Storybook SVG Failed to execute 'createElement' on 'Document'React Storybook SVG 无法在“文档”上执行“createElement”
【发布时间】:2019-06-15 00:03:30
【问题描述】:

我正在尝试将 Storybook 添加到现有的 React 应用程序,但导入的 svg 文件出现错误。 svg 的导入和使用如下:

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

这在应用程序运行和构建时有效,但我在 Storybook 中遇到错误。怎么会?


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.

默认的 webpack.config.js 有:

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

另外,现有代码使用 webpack 3,而我使用的是 Storybook V4。

【问题讨论】:

    标签: reactjs webpack storybook


    【解决方案1】:

    这是为我解决问题的另一种方法

    import Border from './images/border.inline.svg'
    

    然后在你的代码中

    <img src={Border} alt="Border" className="w-25"/>
    

    【讨论】:

      【解决方案2】:

      对我来说,这是因为我使用了错误的标签名称:

      import React from 'react';
      import RMDBLogo from '../../images/react-movie-logo.svg';
      import TMDBLogo from '../../images/tmdb_logo.svg';
      
      
      import { Wrapper, Content,LogoImg,TMDBLogoImg } from './Header.styles';
      
      const Header = () => (
          <Wrapper>
              <Content>
                  <LogoImg src={RMDBLogo} alt='RMDBLogo' />
                  <TMDBLogo src={TMDBLogo} alt='TMDBLogo'/>
              </Content>
          </Wrapper>
      );
      
      export default Header;
      

      我在Content 标签内使用TMDBLogo 标签时导入了TMDBLogoImg 组件。

      【讨论】:

        【解决方案3】:

        Storybook V6 似乎更改了默认的 webpack 配置。我发现上面的答案对我不起作用。

        它们不再有 SVG 规则,因此对 SVG 的测试要么出错,要么返回未定义。

        module.rules 上有一条 oneOf 规则,其中包含一个没有测试的加载器作为最后一条规则:

        {
              loader: '/Users/alexwiley/Work/OneUp/resources/client/node_modules/react-scripts/node_modules/file-loader/dist/cjs.js',
              exclude: [Array],
              options: [Object]
        }
        

        这是罪魁祸首,你需要确保文件加载是排除所有内联SVG文件否则会出错。

        将以下内容添加到您的.storybook/main.js file

        webpackFinal: async(config, { configType }) => {
        config.module.rules.forEach((rule) => {
          if (rule.oneOf) {
            // Iterate over the oneOf array and look for the file loader
            rule.oneOf.forEach((oneOfRule) => {
              if (oneOfRule.loader && oneOfRule.loader.test('file-loader')) {
                // Exclude the inline SVGs from the file loader
                oneOfRule.exclude.push(/\.inline\.svg$/);
              }
            })
            // Push your SVG loader onto the end of the oneOf array
            rule.oneOf.push({
              test: /\.inline\.svg$/,
              exclude: /node_modules/,
              loader: 'svg-react-loader', // use whatever SVG loader you need
            })
          }
        });
        return config;
        

        }

        【讨论】:

          【解决方案4】:

          在 Storybook 6 中,您必须像这样导入它:

          import { ReactComponent as Border } from './images/border.inline.svg'
          

          尝试一下,如果它也适用于您的版本,因为这个问题来自一年前。

          【讨论】:

            【解决方案5】:

            这是因为 Storybook 的 default webpack config 有自己的 svg 配置:

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

            我很确定这是原因,因为您可以看到错误消息中概述的路径:query: { name: 'static/media/[name].[hash:8].[ext]' } -&gt; static/media/border.inline.258eb86a.svg

            解决方案可以是找到现有的加载程序并更改/或为其添加排除规则。以下是自定义.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;
            };
            

            【讨论】:

            • 谢谢!我试过但得到了一些不同的错误。我也刚刚意识到,现有代码使用 webpack 3。 Storybook 需要 v4?我会更新问题
            • 嘿,马克!如果您使用的是 Storybook 4,它将使用 webpack v4。您遇到了哪些不同的错误?
            • 谢谢!我得到 SyntaxError: Duplicate parameter name not allowed in this context with your sn-p.我会看看我是否可以重用我们现在在 webpack 中拥有的那个。再次感谢!
            • ../border.inline.svg 中的错误模块构建失败(来自 ./node_modules/file-loader/dist/cjs.js):类型错误:无法读取对象未定义的属性“上下文” .loader (/xxx/node_modules/file-loader/dist/index.js:34:49) @ ./src/js/components/Card.js 39:0-82 122:29-43 @ ./src/js /components/stories/Card.story.js @ ./src sync .story.js @ ./.storybook/config.js @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./ node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js ./node_modules/webpack-hot-middleware/client.js?reload=true
            • 谢谢@Derek Nguyen!
            【解决方案6】:

            我得到了它的工作

            ...
            module.exports = {
              module: {
                rules: [
                  {
                    test: /\.inline.svg$/,
                    loader: 'svg-react-loader'
                  }
                ]
              }
            }
            

            【讨论】:

              猜你喜欢
              • 2017-03-04
              • 2017-06-02
              • 2020-05-17
              • 2020-08-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多