【问题标题】:Storybook: Failed to execute 'createElement' on svg files using @svgr/webpack故事书:无法使用 @svgr/webpack 对 svg 文件执行“createElement”
【发布时间】:2020-08-13 08:31:32
【问题描述】:

首先我的错误与here 描述的错误完全相同。我正在使用 @svgr/webpack 包将我的 .svg 文件导入为这样的 React 组件:

import Shop from './icons/shop.svg'

return <Shop />

它在我的应用程序上运行良好,但是当我尝试在 Storybook 中做同样的事情时,我收到了这个错误:

无法在“文档”上执行“createElement”:提供的标签名称(“static/media/shop.61b51e05.svg”)不是有效名称。

所以我将加载程序添加到我的.storybook/main.js 文件中以扩展默认的 Storybook webpack 配置:

// ...
webpackFinal: async config => {    
    config.module.rules.push({
      test: /\.svg$/,
      enforce: 'pre',
      loader: require.resolve('@svgr/webpack'),
    });

错误仍然发生,因此我尝试按照answer of the previous question 中的建议覆盖.svg 文件的默认故事书测试:

const fileLoaderRule = config.module.rules.find(rule => { rule.test !== undefined ? rule.test.test('.svg') : '' });
fileLoaderRule.exclude = /\.svg$/;

然后我得到这个错误:

TypeError:无法设置未定义的属性“排除”

所以我决定创建一个rule.testconsole.log,奇怪的是来自 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)$/,
  ...
}

如您所见,没有影响.svg 文件的测试。有人知道为什么我的配置无法使用:

{
  test: /\.svg$/, 
  enforce: 'pre',
  loader: require.resolve('@svgr/webpack'),
}

我的故事书版本是6.0.0-beta.3

【问题讨论】:

    标签: javascript reactjs svg webpack storybook


    【解决方案1】:

    您的find 回调始终返回undefined。更改它以返回正确的布尔值:

    const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'));
    

    无论如何,故事书默认配置应该有一个用于此测试的图像规则: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/。 所以你的代码(但有正确的 find 回调)对我来说很好。

    最终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;
        } 
    };
    

    【讨论】:

    • 我在我的问题中说过,如果我将我的规则设为console.log,则没有/\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/fileLoaderRule 在我的情况下仍然是 undefined
    • 根据您的错误消息,一些 webpack 配置已配置文件加载器......那么您的故事书版本是什么?
    • 很抱歉回答问题。我更新了我的问题。
    • 这终于让我停止了故事书使用 url-loader 处理 svgs!谢谢!
    • 谢谢,折腾了好久,终于成功了。您的答案应该被标记为正确答案。
    【解决方案2】:

    像这样导入它:

    import { ReactComponent as Shop } from './icons/shop.svg'
    

    它将其转换为 React 组件,以便您可以将属性传递给它:

    <Shop fill="tomato" {...args} />
    

    【讨论】:

      猜你喜欢
      • 2019-11-06
      • 2019-06-15
      • 2021-07-23
      • 2018-09-19
      • 2023-01-15
      • 2021-01-12
      • 2019-01-02
      • 2021-05-12
      • 2017-10-05
      相关资源
      最近更新 更多