无法将SVG导入Next JS?

时间:2019-03-15 04:13:27

标签: reactjs webpack-4 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>

9 个答案:

答案 0 :(得分:8)

我个人更喜欢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标签。

答案 1 :(得分:7)

您可以使用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"
  ]
}

或查看链接以获取更多说明。

答案 2 :(得分:3)

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

为了配置它以便下次使用,您需要将加载程序的用法添加到next.config.js文件中,如下所示:

// next.config.js

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

    return config;
  }
};

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

别忘了先安装:npm install @svgr/webpack

答案 3 :(得分:2)

您只需通过 img 标签将其导入。

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

只需确保svg位于公共文件夹中即可。

答案 4 :(得分:2)

快捷方式:<img><Image>

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

可以使用官方的 next/image 包或 img 标记(如本 answer 中所述)。

您只需将 svg 文件移动到 public 而不是 static,然后执行以下操作:

import Image from 'next/img';

// ...

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

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

还需要指定 widthheight,但您可以通过 viewbox 属性计算。

在 Next.js v11 上,您还可以:

import Image from 'next/img';

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

// ...

<Image src={Illustration} />

在 HTML 中包含 SVG(用于 webpack-5、TS)

accepted answer 已经展示了如何使用 webpack-4 执行此操作,但由于 webpack-5 现在是默认设置,因此我将共享适当的配置。您可以在安装 @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;
  },
};

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

// index.d.ts

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

然后你可以像这样使用它:

import Logo from '@assets/logo.svg';

// ...

<Logo />

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

[过时 (Fixed)] 更新:

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

答案 5 :(得分:1)

安装next-images

yarn add -D next-images

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

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

答案 6 :(得分:0)

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

// In next.config.js

const withSass = require('@zeit/next-sass');
const withCSS = require("@zeit/next-css");

module.exports = withCSS(withSass({
    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;
    }
}));

答案 7 :(得分:0)

您可以使用 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

答案 8 :(得分:0)

How to import SVG into Next.js component?

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

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