无法将 SVG 导入 Next.js

Can't import SVG into Next.js

当我尝试导入 SVG 图像时,出现以下错误。我必须使用哪个加载器来导入 SVG 图像?

./static/Rolling-1s-200px.svg 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000"><filter id="b"><feGaussianBlur stdDeviation="12" /></filter><path fill="#817c70" d="M0 0h2000v2000H0z"/><g filter="url(#b)" transform="translate(4 4) scale(7.8125)" fill-opacity=".5"><ellipse fill="#000210" rx="1" ry="1" transform="matrix(50.41098 -3.7951 11.14787 148.07886 107 194.6)"/><ellipse fill="#eee3bb" rx="1" ry="1" transform="matrix(-56.38179 17.684 -24.48514 -78.06584 205 110.1)"/><ellipse fill="#fff4bd" rx="1" ry="1" transform="matrix(35.40604 -5.49219 14.85017 95.73337 16.4 123.6)"/><ellipse fill="#79c7db" cx="21" cy="39" rx="65" ry="65"/><ellipse fill="#0c1320" cx="117" cy="38" rx="34" ry="47"/><ellipse fill="#5cb0cd" rx="1" ry="1" transform="matrix(-39.46201 77.24476 -54.56092 -27.87353 219.2 7.9)"/><path fill="#e57339" d="M271 159l-123-16 43 128z"/><ellipse fill="#47332f" cx="214" cy="237" rx="242" ry="19"/></g></svg>

您需要提供一个 webpack 加载程序来处理 SVG 导入,其中一个著名的是 svgr

为了将其配置为与 next 一起使用,您需要将加载程序的用法添加到 next.config.js 文件中,如下所示:

// next.config.js
    
module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: {
        test: /\.(js|ts)x?$/,
       // for webpack 5 use
       // { and: [/\.(js|ts)x?$/] }
      },
      
      use: ['@svgr/webpack'],
    });

    return config;
  },
};

有关更多配置信息,check out the docs

别忘了先安装@svgr/webpack:

$ npm install --save-dev @svgr/webpack

编辑

我添加了一个 issuer 部分,该部分将这些 svg 严格限制为仅适用于从 js / ts 文件导入的 svg 的组件。 这允许您为从其他文件类型(例如 .css)导入的 svgs 配置其他行为

安装next-images.

yarn add -D next-images

在您的项目中创建一个 next.config.js

// next.config.js
const withImages = require('next-images')
module.exports = withImages()

这对我有用,没有任何其他依赖性

// In next.config.js

module.exports = {
    webpack (config, options) {
        config.module.rules.push({
            test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
            use: {
                loader: 'url-loader',
                options: {
                    limit: 100000
                }
            }
        });
        return config;
    }
};

您可以使用babel-plugin-inline-react-svg

import React from 'react';
import CloseSVG from './close.svg';

const MyComponent = () => <CloseSVG />;
npm install --save-dev babel-plugin-inline-react-svg
// .babelrc
{
  "plugins": [
    "inline-react-svg"
  ]
}

或参阅 link 了解更多说明。

我个人更喜欢 next-react-svg 插件,它允许将 SVG 图像视为 React 组件并自动内联它们,类似于 Create React App 所做的。

使用方法如下:

  1. 安装next-react-svg:
npm i next-react-svg
  1. 将必要的设置添加到 next.config.js:
const withReactSvg = require('next-react-svg')
const path = require('path')

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

include 参数是必需的,它指向您的 SVG 图像文件夹。

如果您已经为您的 Next.js 启用了任何插件,请考虑使用 next-compose-plugins 来正确组合它们。

  1. 将您的 SVG 作为普通 React 组件导入:
import Logo from 'assets/svg/Logo.svg';

export default () => (
  <Logo />
);

就是这样。从现在开始,Next.js 将以这种方式将 SVG 图像作为 SVG 标签导入到呈现的标记中。

您只需通过 <img> 标签导入即可。

<img src='./next.svg' alt='next' />

只需确保 svg 在 public 文件夹中。

您可以使用 next-plugin-svgrnext-compose-plugins 清理插件(如果您有):

// next.config.js
const withPlugins = require("next-compose-plugins");
const withSvgr = require("next-svgr");
 
module.exports = withPlugins([
  withSvgr
  // your other plugins here
]);

next-plugin-svgr:

// next.config.js
const withSvgr = require('next-plugin-svgr');
 
module.exports = withSvgr({
  webpack(config, options) {
    return config;
  },
});

来源:https://www.npmjs.com/package/next-plugin-svgr

快捷方式:<img><Image>

Not suitable for interactive SVGs or if you intend to manipulate a SVG by external CSS/JS

可以用官方next/image component or img tag (as mentioned in this ).

您只需将 svg 文件从 static 移动到 public,然后执行如下操作:

import Image from 'next/image';

// ...

<Image src="/Rolling-1s-200px.svg" width="2000" height="2000" />

但是通过使用这种方法,svg文件的内容将不会直接出现在响应中;浏览器将获得一个 <img src="..." ...></img> 标签。

还需要指定widthheight,但可以从viewbox属性中计算出来。

在 Next.js v11 及更高版本上,您还可以:

import Image from 'next/image';

import Illustration from '../static/Rolling-1s-200px.svg';

// ...

<Image src={Illustration} />

// one needs to use `Illustration.src` to get the source URL
// <img src={Illustration.src} ... />

在内部包含 SVG HTML(对于 webpack-5、TS)

has shown how to do this with webpack-4, but since webpack-5 is now default, I'm sharing the appropriate config. You can use it after installing @svgr/webpackyarn add -D @svgr/webpacknpm install @svgr/webpack --save-dev):

// next.config.js
// https://github.com/gregberge/svgr/issues/551#issuecomment-839772396

module.exports = {
  // other configs...

  // future: { webpack5: true }, // -- not needed since Next.js v11.0.0
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/i,
      issuer: { and: [/\.(js|ts|md)x?$/] },
      use: [
        {
          loader: '@svgr/webpack',
          options: {
            prettier: false,
            svgo: true,
            svgoConfig: { plugins: [{ removeViewBox: false }] },
            titleProp: true,
          },
        },
      ],
    });
    return config;
  },
};

如果你没有使用 options 作为加载程序,那么你可以简单地写成这样:

use: ['@svgr/webpack']

如果您使用的是 @svgr/webpack 的 v6,那么您需要像这样指定 SVGO 配置:

// ...

plugins: [
  {
    name: 'preset-default',
    params: {
      overrides: { removeViewBox: false },
    },
  },
],

// ...

如果使用打字稿,您需要定义适当的模块(在您导入的目录中 svg,或者可能将其作为 <some-name>.d.ts 添加到根目录并包含它 tsconfig ):

// index.d.ts

declare module '*.svg' {
  const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  export default ReactComponent;
}

那么你可以这样使用它:

import Illustration from '../static/Rolling-1s-200px.svg';

// ...

<Illustration />

注意:Next.js v11.0.1+ 已将 SVG 声明为模块导出 any。您的自定义配置不会覆盖 next-env.d.ts 设置的类型,除非您排除后者。请参考.

[已过时(Fixed] 更新:

如果您使用的是 Next.js v11.0.0,那么您在导入 SVG 时可能会遇到错误。请更新至 v11.0.1 或以上。 请遵循 this comment 中提到的解决方法。

另一种不安装任何库的解决方案

import React from "react";
export default function GoogleLogo() {
  return (
    <svg className="svgIcon-use" width="25" height="37" viewBox="0 0 25 25">
      <g fill="none" fillRule="evenodd">
        <path
          d="M20.66 12.693c0-.603-.054-1.182-.155-1.738H12.5v3.287h4.575a3.91 3.91 0 0 1-1.697 2.566v2.133h2.747c1.608-1.48 2.535-3.65 2.535-6.24z"
          fill="#4285F4"
        />
        <path
          d="M12.5 21c2.295 0 4.22-.76 5.625-2.06l-2.747-2.132c-.76.51-1.734.81-2.878.81-2.214 0-4.088-1.494-4.756-3.503h-2.84v2.202A8.498 8.498 0 0 0 12.5 21z"
          fill="#34A853"
        />
        <path
          d="M7.744 14.115c-.17-.51-.267-1.055-.267-1.615s.097-1.105.267-1.615V8.683h-2.84A8.488 8.488 0 0 0 4 12.5c0 1.372.328 2.67.904 3.817l2.84-2.202z"
          fill="#FBBC05"
        />
        <path
          d="M12.5 7.38c1.248 0 2.368.43 3.25 1.272l2.437-2.438C16.715 4.842 14.79 4 12.5 4a8.497 8.497 0 0 0-7.596 4.683l2.84 2.202c.668-2.01 2.542-3.504 4.756-3.504z"
          fill="#EA4335"
        />
      </g>
    </svg>
  );
}

并使用:

import GoogleLogo from "./GoogleLogo";

  class Login extends React.Component {
    render() {
      return (
        <LoginLayout title="Login Page">
          <div>
            <Link href="/auth/google">
              <a className="button">
                <div>
                  <span className="svgIcon t-popup-svg">
                    <GoogleLogo />
                  </span>

                </div>
              </a>
            </Link>
          </div>
        </LoginLayout>
      );
    }
  }

我尝试了第一个答案,但出现错误,所以这个有效:

module.exports = {
webpack(config) {
  config.module.rules.push({
    test: /\.svg$/,
    use: ["@svgr/webpack"]
  });

  return config;
}};

Next.js 12.0.9Webpack 5 这对我有用:

yarn add --dev url-loader @svgr/webpack
// next.config.js
module.exports = {
    webpack(config, options) {
        config.module.rules.push({
          test: /\.svg$/,
          use: ['@svgr/webpack', 'url-loader'],
        });
    
        return config;
    },
  };

如果您想在代码中使用 SVG 文件无需任何配置或安装依赖项并且完全控制标签的属性,最好的解决办法是将SVG文件转换为JSX或TSX组件。

JSX解决方案:

export const YourSVg = ({color, width, height}) => (
   <svg fill={color} height={height} width={width}>
    ..rest of the svg tags...
   </svg>
)

TSX解决方案:

   export const YourSVg:React.FC<{color:string, width:string, height:string}> =
       ({color, width, height}) => (
          <svg color={color} height={height} width={width}>
            ..rest of the svg tags...
          </svg>
    )

如何使用?

可以像普通组件一样导入并像以前一样使用

例如:

import YourSVg from '../from the path/path


<YourSVg color='red' width='10px' height='10px/>