[英]Storybook: Failed to execute 'createElement' on svg files using @svgr/webpack
My error in the first place is exactly the same as the one described here .我的错误首先与此处描述的错误完全相同。 I'm using the @svgr/webpack package to import my .svg
files as a React component like that:我正在使用@svgr/webpack package 将我的.svg
文件导入为 React 组件,如下所示:
import Shop from './icons/shop.svg'
return <Shop />
It works fine on my app but when I tried to do the same in Storybook I get this error:它在我的应用程序上运行良好,但当我尝试在Storybook中执行相同操作时,出现此错误:
Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/shop.61b51e05.svg') is not a valid name.无法在“Document”上执行“createElement”:提供的标签名称(“static/media/shop.61b51e05.svg”)不是有效名称。
So I added the loader into my .storybook/main.js
file to extends the default Storybook webpack config:所以我将加载程序添加到我的.storybook/main.js
文件中以扩展默认的 Storybook webpack 配置:
// ...
webpackFinal: async config => {
config.module.rules.push({
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('@svgr/webpack'),
});
The error still occurred so I tried to override the default Storybook test for .svg
files as suggested in the answer of the previous question :错误仍然发生,所以我尝试按照上一个问题的答案中的建议覆盖.svg
文件的默认 Storybook 测试:
const fileLoaderRule = config.module.rules.find(rule => { rule.test !== undefined ? rule.test.test('.svg') : '' });
fileLoaderRule.exclude = /\.svg$/;
But then I get this error:但后来我得到这个错误:
TypeError: Cannot set property 'exclude' of undefined类型错误:无法设置未定义的属性“排除”
So I decided to make a console.log
of the rule.test
and strangely the only default tests coming from Storybook config are theses:所以我决定制作一个console.log
的rule.test
奇怪的是,来自 Storybook 配置的唯一默认测试是这些:
{
test: /\.md$/,
...
}
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
...
}
{
test: /\.js$/,
...
}
{
test: /\.(stories|story).mdx$/,
...
}
{
test: /\.mdx$/,
...
}
{
test: /\.(stories|story)\.[tj]sx?$/,
...
}
{
test: /\.(ts|tsx)$/,
...
}
As you can see there is no test that affects a .svg
file.如您所见,没有影响.svg
文件的测试。 So does someone have an idea why my configuration is not working using:那么有人知道为什么我的配置无法使用:
{
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('@svgr/webpack'),
}
My storybook version is 6.0.0-beta.3
.我的故事书版本是6.0.0-beta.3
。
Your find
callback always returns undefined
.您的find
回调始终返回undefined
。 Change it to return correct bool:更改它以返回正确的布尔值:
const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'));
Anyway storybook default config should have a rule for images with this test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
.无论如何,故事书默认配置应该有一个用于此测试的图像规则: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
。 So your code (but with correct find callback) works fine for me.所以你的代码(但有正确的查找回调)对我来说很好。
Final main.js
:最终main.js
:
module.exports = {
stories: ['../src/**/*.stories.[tj]s'],
webpackFinal: config => {
// Default rule for images /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'));
fileLoaderRule.exclude = /\.svg$/;
config.module.rules.push({
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('@svgr/webpack'),
});
return config;
}
};
Since I'm using webpack@4
, and therefore @svgr/webpack@5
, I had to use url-loader
.由于我使用的是webpack@4
和@svgr/webpack@5
,所以我不得不使用url-loader
。
module.exports = {
stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)'],
webpackFinal: config => {
// remove svg from existing rule
const fileLoaderRule = config.module.rules.find(
(rule) => rule.test && rule.test.test('.svg')
)
fileLoaderRule.exclude = /\.svg$/
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack', 'url-loader'],
})
return config
}
};
I tried all methods written here, but always got an error:我尝试了这里写的所有方法,但总是出错:
TypeError: Cannot set property 'exclude' of undefined类型错误:无法设置未定义的属性“排除”
Finally, i consoled config.module.rules
and saw its structure: the needed rule is config.module.rules[5].oneOf[2]
.最后,我安慰config.module.rules
并看到了它的结构:所需的规则是config.module.rules[5].oneOf[2]
。 So i've just hardcoded it with: config.module.rules[5].oneOf[2] = ['@svgr/webpack']
.所以我只是硬编码它: config.module.rules[5].oneOf[2] = ['@svgr/webpack']
。
I think that it's a temporary dirty solution, but it works.我认为这是一个临时的肮脏解决方案,但它确实有效。 Hope somebody will point out how to make it more clean and bulletproof.希望有人会指出如何使它更干净和防弹。
Just import it like this:只需像这样导入它:
import { ReactComponent as Shop } from './icons/shop.svg'
It's transforming it as a React Component so that you can pass properties to it:它将其转换为 React 组件,以便您可以将属性传递给它:
<Shop fill="tomato" {...args} />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.