Storybook:无法使用@svgr/webpack在svg文件上执行“安装元素”

new9mtju  于 2023-10-19  发布在  Webpack
关注(0)|答案(5)|浏览(144)

首先,我的错误与here描述的错误完全相同。我使用@svgr/webpack包将我的.svg文件作为React组件导入,如下所示:

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

return <Shop />

它在我的应用程序上运行良好,但当我试图在Storybook中执行相同操作时,我得到了以下错误:
无法对“Document”执行“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'),
    });

错误仍然发生,所以我试图覆盖.svg文件的默认Storybook测试,如answer of the previous question中所建议的:

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

然后我得到了这个错误:
TypeError:无法设置未定义的“exclude”属性
所以我决定做一个rule.testconsole.log,奇怪的是,来自Storybook配置的唯一默认测试是these:

{
  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

tktrz96b

tktrz96b1#

您的find回调始终返回undefined。将其更改为返回正确的bool:

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;
    } 
};
niknxzdl

niknxzdl2#

由于我使用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
  }
};
vcirk6k6

vcirk6k63#

我尝试了这里写的所有方法,但总是得到一个错误:
TypeError:无法设置未定义的“exclude”属性
最后,我控制了config.module.rules,看到了它的结构:所需的规则是config.module.rules[5].oneOf[2]。所以我硬编码了它:config.module.rules[5].oneOf[2] = ['@svgr/webpack']
我认为这是一个暂时的肮脏的解决方案,但它的工作。希望有人能指出如何使它更干净和防弹。

b0zn9rqh

b0zn9rqh4#

{
webpackFinal: async (config: Configuration) => {
        config.module = config.module || {};
        config.module.rules = config.module.rules || [];
    
        const imageRule = config.module.rules.find((rule) => rule?.['test']?.test('.svg'));
        if (imageRule) {
          imageRule['exclude'] = /\.svg$/;
        }
    
        config.module.rules.push({
          test: /\.svg$/,
          use: ['@svgr/webpack'],
        });
        return config
})


}
rdlzhqv9

rdlzhqv95#

像这样导入:

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

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

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

相关问题