【问题标题】:Importing SVG files dynamically in NextJS在 NextJS 中动态导入 SVG 文件
【发布时间】:2021-09-23 08:41:44
【问题描述】:

我正在尝试动态导入我们用来提高性能的 SVG 文件。现在我们使用静态导入,因此它会在 HTML 构建中添加所有 svg 文件,即使我们每页只需要几个文件。这会增加页面加载时间,因为HTML 文件更大,因此下载和读取HTML 文件需要更长的时间。

在当前设置下,页面首先加载,但随后显示空白屏幕。这样做的原因是因为它在加载时首先加载了<span/>,然后将其替换为svg,但由于导入不顺利,它会崩溃并显示一个空白屏幕。

该项目是一个 NextJS 项目,使用 Webpack 运行。这是我用来导入SVG 文件的代码:

export const Chevron = dynamic(
  () => import('./Icons/chevron.svg'), 
    {
      loading: () => <span/>,
      ssr: false,
    }
  )

您会在下面找到我遇到的错误。注意前面的&lt; 和后面的/&gt;,这似乎表明它正在尝试将base64 字符串解析为JSX.Element

Warning: <data:image/svg+xml;base64,dmFyIF9wYXRoOwoKZnVuY3Rpb24gX2V4dGVuZHMoKSB7IF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTsgcmV0dXJuIF9leHRlbmRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7IH0KCmltcG9ydCAqIGFzIFJlYWN0IGZyb20gInJlYWN0IjsKCmZ1bmN0aW9uIFN2Z0Fycm93U21hbGxVcChwcm9wcykgewogIHJldHVybiAvKiNfX1BVUkVfXyovUmVhY3QuY3JlYXRlRWxlbWVudCgic3ZnIiwgX2V4dGVuZHMoewogICAgeG1sbnM6ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIsCiAgICB3aWR0aDogNiwKICAgIGhlaWdodDogMTMsCiAgICB2aWV3Qm94OiAiMCAwIDYgMTMiCiAgfSwgcHJvcHMpLCBfcGF0aCB8fCAoX3BhdGggPSAvKiNfX1BVUkVfXyovUmVhY3QuY3JlYXRlRWxlbWVudCgicGF0aCIsIHsKICAgIGZpbGw6ICIjRkZGIiwKICAgIGQ6ICJNMy4wNTUgMGEuMzY4LjM2OCAwIDAxLjE1NS4wNTNsLjA2Ny4wNTMgMi42MiAyLjYyYy4xMjUuMTI0LjE0Mi4zMTYuMDUyLjQ2bC0uMDU0LjA2Ny0uMDY4LjA1NGEuMzczLjM3MyAwIDAxLS4zOTIuMDAybC0uMDY3LS4wNTMtMS45ODQtMS45ODNoLS4wMzJ2MTAuNzYzYzAgLjE3LS4xMi4zMS0uMjc5LjM0M2wtLjA3LjAwN2EuMzUuMzUgMCAwMS0uMzQzLS4yOGwtLjAwNy0uMDctLjAwMS0xMC43NjNoLS4wMzFMLjYzOCAzLjI1NmEuMzcyLjM3MiAwIDAxLS40Ni4wNTFsLS4wNjctLjA1NGEuMzczLjM3MyAwIDAxLS4wMDMtLjUyN2wyLjYyLTIuNjJBLjM2Ny4zNjcgMCAwMTIuOTUxIDBoLjEwNHoiCiAgfSkpKTsKfQoKZXhwb3J0IGRlZmF1bHQgU3ZnQXJyb3dTbWFsbFVwOw== /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.

这是我的下一个配置:

  const withFonts = require('next-fonts');
  const withTM = require('next-transpile-modules');

  module.exports = withTM(
    withFonts({
      useFileSystemPublicRoutes: false,
      enableSvg: true,
      webpack(config) {
        config.module.rules.push({
          test: /\.svg$/,
          use: [
            {
              loader: '@svgr/webpack',
              options: {
                svgoConfig: {
                  plugins: {
                    removeViewBox: false,
                  },
                },
              },
            },
          ],
        });

        return config;
      },
      assetPrefix: '/_react',
      transpileModules: [
        'swiper',
        'dom7',
        'query-string',
        'strict-uri-encode',
        'split-on-first',
        'set-harmonic-interval',
      ],
    }),
  );

【问题讨论】:

  • 为什么不简单地像这样使用它import foo from 'path/to/foo.svg'; import Image from 'next/image'; ... &lt;Image src={foo} /&gt; 另外请在问题中添加您的 webpack/next 配置和版本。您遇到的不是默认行为。
  • @brc-dd 我用您要求的答案编辑了我的问题
  • next/dynamic 用于导入 React 组件,但您正在尝试导入 SVG。尝试创建一个呈现 SVG 的组件,然后改为动态导入该组件。

标签: reactjs svg webpack import next.js


【解决方案1】:

如果您使用 next-images 导入 SVG 文件,则需要将它们用作纯图像。如果您更喜欢将 SVG 作为 React 组件导入,并且仍想使用 next-images 来导入其他图像,那么您应该自定义配置以省略保存 SVG 的目录并使用 SVGRbabel-plugin-react-svg 用于您的 SVG 文件。

// next.config.js
const path = require('path');
const withImages = require('next-images');

module.exports = withImages({
  exclude: path.resolve(__dirname, 'src/assets/svg'),
  webpack(config, options) {
    return config
  }
})

【讨论】:

    猜你喜欢
    • 2020-07-10
    • 2020-10-18
    • 2019-05-28
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 2021-06-03
    相关资源
    最近更新 更多