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]' -> 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 不会在 Vue 项目的组件中加载 SVG