Не удается импортировать SVG в 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>

Чтобы решить эту проблему удобным способом, я использую плагин next-react-svg. Вот как stackoverflow.com/a/61854576/1762849

Konstantin Komelin 17.05.2020 18:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
59
2
85 733
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Ответ принят как подходящий

Вам нужно предоставить загрузчик веб-пакетов, который будет обрабатывать импорт SVG, один из известных — СВГР.

Чтобы настроить его для работы со следующим, вам нужно добавить в свой файл 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;
  },
};

Для получения дополнительной информации о конфигурации проверить документы.

Не забывайте, чтобы сначала установить @svgr/webpack:

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

Редактировать

Я добавил раздел issuer, который ограничивает эти svg как компоненты только для svg, импортированных из файлов js / ts. Это позволяет настроить другое поведение для svg, которые импортируются из других типов файлов (например, .css).

следующий-svgr — плагин Next более высокого уровня, реализующий то же решение. однако на данный момент он не поддерживает параметр issuer.
Konstantin Komelin 25.05.2020 17:33

Да, это не буэно @felixmosh

Robbie Cook 05.07.2021 09:38

для webpack5 используйте issuer: { and: [/\.(js|ts)x?$/] }

banyudu 18.07.2021 13:56

Установите следующие изображения.

yarn add -D next-images

Создайте next.config.js в своем проекте.

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

Для тех, кто использует Typescript, не забудьте добавить: /// <reference types = "next-images" /> в ваш файл next-env.d.ts.

Jean Bauer 19.04.2020 15:30

Это сработало для меня без какой-либо другой зависимости

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

Это лучший ответ. Чистая конфигурация Webpack. Нет необходимости ничего устанавливать.

Dayron Gallardo 01.04.2020 22:18

@DayronGallardo «не нужно ничего устанавливать», а? Вы должны установить @zeit/next-sass и @zeit/next-css

Brandon 05.08.2020 20:24

@BrandonDuffany нет, вам не нужно их устанавливать. Ответчик скопировал свою собственную конфигурацию, поэтому в блоке кода присутствуют эти служебные оболочки. Вам вообще не нужно их использовать.

brc-dd 27.10.2021 07:31

Вы можете использовать Babel-плагин-встроенный-реагировать-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"
  ]
}

Или смотрите ссылку для получения дополнительных инструкций.

По какой-то причине это не будет работать в проекте Typescript.

Rafael 'BSIDES' Pereira 28.04.2021 22:31

1. Абсолютные пути не поддерживаются. 2. Вы должны установить окно просмотра вручную, потому что этот плагин не импортирует его из файла svg. 3. Не работает с машинописным текстом. Неужели нет простого решения?? Nextjs существует уже много лет, а этот вопрос был задан в 2019 году!

VityaSchel 16.07.2021 12:55

Лично я предпочитаю плагин следующий-реагировать-SVG, который позволяет обрабатывать изображения SVG как компоненты React и автоматически встраивать их, подобно тому, как это делает приложение Create React.

Вот как это использовать:

  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, рассмотрите возможность использования следующий компоновщик-плагины для их правильного объединения.

  1. Импортируйте свои SVG как обычные компоненты React:
import Logo from 'assets/svg/Logo.svg';

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

Вот и все. Отныне Next.js будет включать изображения SVG, импортированные таким образом, в отображаемую разметку в виде тегов SVG.

Вы знаете, как использовать next-react-svg со сборником рассказов?

Sujan Thakare 25.02.2021 09:03

Это большое спасибо. Если вы пришли из приложения Create React, как и я, обязательно измените оператор импорта SVG. то есть изменить import { ReactComponent as MySvg } from 'src/assets/mysvg.svg'. в import MySvg from 'src/assets/mysvg.svg'

jboxxx 10.03.2021 03:48

Вы можете просто импортировать его через тег <img>.

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

Просто убедитесь, что svg находится в общей папке.

Этот ответ вводит в заблуждение, поскольку контекст здесь SVG как SVG, но не как изображение.

Navaneeth 10.03.2021 21:21

используя этот метод, svg не будет отображаться в браузере

shashwat gupta 07.07.2021 07:35

Вы можете использовать next-plugin-svgr и next-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>

Не подходит для интерактивных SVG или если вы собираетесь манипулировать SVG с помощью внешнего CSS/JS.

Можно использовать официальный компонент next/image или тег img (как указано в этом отвечать).

Вам просто нужно переместить файл svg в public вместо static и сделать что-то вроде этого:

import Image from 'next/image';

// ...

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

Но при использовании этого метода содержимое файла svg не будет присутствовать непосредственно в ответе; браузер получит тег <img src = "..." ...></img>.

Также нужно указать width и height, но можно посчитать из атрибута 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)

принятый ответ показал, как это сделать с помощью webpack-4, но поскольку webpack-5 теперь используется по умолчанию, я делюсь соответствующей конфигурацией. Вы можете использовать его после установки @svgr/webpack (yarn add -D @svgr/webpack или npm 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']

Если вы используете v6 of @svgr/webpack, вам нужно указать конфигурацию 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, если вы не исключите последний. См. это.

[УСТАРЕЛО (Фиксированный)] ОБНОВИТЬ :

Если вы используете Next.js v11.0.0, вы можете получать ошибки при импорте SVG. Пожалуйста, обновите до v11.0.1 или выше. Воспользуйтесь обходным решением, упомянутым в этот комментарий.

Могу ли я использовать .svg из каталога public/? в настоящее время я создал assets/ только для использования относительного импорта с использованием TS, такого как @/assets/logo.svg, но хотел бы использовать его только из public/. Является ли это возможным?

deadcoder0904 30.06.2021 12:38

@ deadcoder0904 Пожалуйста, обратитесь к первой части ответа. Переместите свои SVG в public и используйте их вот так <Image src = "/svg-name.svg" height = "100" width = "100" />. Вы также можете переместить папку с активами прямо в каталог public; тогда вам нужно будет передать src как /assets/svg-name.svg.

brc-dd 30.06.2021 12:52

нет, мне нужно импортировать его. я не хочу использовать компонент Image. эта часть отсутствует в вашем ответе, и это именно то, что я хочу сделать.

deadcoder0904 30.06.2021 14:25

@ deadcoder0904 Тогда это невозможно. Я имею в виду, что вы можете сохранить SVG в public или любой другой папке, но вам нужно будет указать полный путь, например @/public/logo.svg, при импорте. Вторая часть ответа показывает это. Вам не нужно использовать компонент Image в этом.

brc-dd 30.06.2021 14:32

Обратите внимание, что: assets — это просто обычное имя папки, это не то, что Next.js понимает сам по себе. Если вы хотите поместить активы в сам каталог public, это тоже нормально; вам просто нужно изменить оператор импорта: import Logo from '@/public/logo.svg'; Но имейте в виду, что общая папка доступна всем, кто посещает ваш сайт, поэтому не помещайте туда ничего конфиденциального.

brc-dd 30.06.2021 14:39

о, да! next.js понимает только pages/ и api/, я думаю. Я использую папку src/ и папку public/ в одном каталоге, используя псевдонимы, и я использовал только псевдонимы внутри src/, поэтому я не устанавливал псевдонимы для public/ и думал, что смогу import Logo from '/logo.svg' импортировать из public/, но это не сработало. благодаря вашим обоим комментариям теперь это имеет смысл.

deadcoder0904 30.06.2021 14:46

@ deadcoder0904 Вы можете использовать такой путь: "@/*": ["src/*", "public/*"] тогда import Logo from '@/Logo.svg'; будет работать.

brc-dd 30.06.2021 15:08

По-прежнему появляется сообщение «Возможно, вам понадобится соответствующий загрузчик для обработки этого типа файла, в настоящее время загрузчики не настроены для обработки этого файла», а затем «Ошибка: не удается найти модуль«.../pages-manifest.json’», потому что веб-пакет может « t read config :( Возможно, это связано с sentry или next-transpile-modules, но когда я не использую их в конфигурации, абсолютные пути перестают работать. Думаю, мне придется использовать префикс в импорте.

VityaSchel 16.07.2021 13:09

@VityaSchel Можете ли вы опубликовать другой вопрос, показывающий, что пошло не так и как это воспроизвести? Обсуждение вашего запроса здесь, в разделе комментариев, не принесет пользы сообществу. И, насколько мне известно, вторая ошибка возникает в основном из-за сбоя в сборке веб-пакета (первая ошибка). Можете ли вы попробовать, если решения, упомянутые в этой теме, работают: github.com/vercel/next.js/issues/6287

brc-dd 16.07.2021 14:32
<Image src = {Illustration} /> сработало!
Stephane 29.01.2022 16:23

Как импортировать SVG в компонент Next.js?

Другое решение без установки какой-либо библиотеки

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.9 и Webpack 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;
    },
  };

вам даже не нужно url-loader

deadcoder0904 10.02.2022 11:14

@ deadcoder0904 для меня без «url-loader» nextjs не может загрузить SVG и выдает ошибку. Мне тоже интересно, почему, но это необходимо.

kepes 10.02.2022 19:51

Если вы хотите использовать файлы 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/>

Другие вопросы по теме