Typescript create-react-app 上 require.context 中的 Webpack 加载器

Webpack loaders in require.context on a Typescript create-react-app

我的 svg 图标太多了,无法按照推荐的方式全部导入:

import { ReactComponent as Icon } from 'assets/svg/icon.svg'

所以在我的 JS React 应用程序中,我一直在使用 webpack 的 require.context 来索引整个 svg 目录并将其导出为对象,然后允许我这样做:

import { svg } from 'assets'

function SvgIcon({ icon }) {
  const Icon = svg[icon]
  return <Icon />
}

/* ... */

<SvgIcon icon='inbox' />

这对我的用例来说太棒了,因为我可以动态加载我需要的所有图标,甚至不必单独导入它们。然而,一旦我切换到 Typescript,require.context 就停止使用 svg 加载器。这段代码,以前可以完美运行,现在只有 returns { [filename]: "/path/to/filename.39843398.svg" },如果我根本不使用 loader 就会出现这种情况。该字符串应该是一个 ReactComponent。

const assets = context =>
  context.keys().reduce((assets: any, path) => {
    const key = path.replace(/^\.\//, '').replace(/\..*$/, '')
    assets[key] = context(path).default || context(path)
    return assets
  }, {})

export const svg = assets(require.context('!@svgr/webpack!./svg', false, /\.svg$/))

Codesandbox 似乎不支持 require.context,但您可以通过使用 --template typescript 创建 React 应用程序、安装 @svgr/webpack、添加 assets/svg 来轻松重现这一点], 在那里复制 logo.svg,制作一个 index.ts 并复制上面的代码块。

根据您的包管理器和 sdk,您可能需要 fiddle 稍微配置一下。我必须安装 @types/webpack-env 并将它们添加到 tsconfig.json 中,如下所示:

{
  /* ... */
  "types": ["node", "webpack-env"]
}

原来罪魁祸首是react-scripts@5.0.0。降级到@4.0.3 解决了这个问题。

顺便说一句,@5.0.0 在处理 svg 文件时还有其他问题,比如没有将命名空间标签转换为正确的 JSX。可能相关,也可能无关。