React Storybook SVG 无法在“文档”上执行“createElement”

Posted

技术标签:

【中文标题】React Storybook SVG 无法在“文档”上执行“createElement”【英文标题】:React Storybook SVG Failed to execute 'createElement' on 'Document' 【发布时间】: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。

【问题讨论】:

【参考方案1】:

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

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

然后在你的代码中

<img src=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'
      
    ]
  

【讨论】:

以上是关于React Storybook SVG 无法在“文档”上执行“createElement”的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将本地 svg 文件包含到我与自定义 Angular 库一起使用的 Storybook 中?

无法在 Storybook 中按类名设置我的 React 组件样式

Storybook 无法导入 Swiper 模块

Storybook 不会在 Vue 项目的组件中加载 SVG

Storybook - 无法模拟嵌套的 React-Router-Dom 链接而不抛出无尽的 NPM 错误

使用 Redux 在 React Hooks 应用程序中添加 Storybook 旋钮