I use SVG files as a component with "@svgr/webpack", How to use next/image module with it

1.8k views Asked by At

In some places, I need to import my SVG file as a component, to have a control on it ( change style for example, change the fill color of the SVG element ) I used SVGR for that, and in other places, I want to use the SVG file as a normal image and get benefit with the built-in "next/image" module features.

I can't use next/image module as when I import it like

import FacebookIcon from "public/images/icons/social/facebook.svg";

FacebookIcon is a component.

Not a format that the src attribute of next/image component can accept.

From what I understood is src accept string or object with this format

{ src: "**", width: **px, height: **px }
1

There are 1 answers

0
Loki On

Desired usage

import MySVG from "./mySVG.svg?svgr"; // SVGR loader

<MySVG />

import Image from "next/image";
import mySVG from "./mySVG.svg"; // Default NextJS loader

<Image src={mySVG} alt="" /> // (width and height will be applied automatically)

Required next.config.js

webpack(config, { dev: isDev, isServer }) {

    config.module.rules.push({
      test: /\.svg$/i,
      issuer: /\.[jt]sx?$/,
      resourceQuery: /svgr/, // only use svgr to load svg if path ends with *.svg?svgr
      use: ["@svgr/webpack"],
    });

    // Re-add default nextjs loader for svg
    config.module.rules.push({
      test: /\.svg$/i,
      loader: "next-image-loader",
      issuer: { not: /\.(css|scss|sass)$/ },
      dependency: { not: ["url"] },
      resourceQuery: { not: [/svgr/] }, // Ignore this rule if the path ends with *.svg?svgr
      options: { isServer, isDev, basePath: "", assetPrefix: "" },
    });

}

Required typescript declaration (if using ts)

declare module "*.svg?svgr";

How I figured it out

  1. Read these docs: https://react-svgr.com/docs/webpack/
  2. Used this snippet to get the default rule applying to svgs
webpack(config) {
    const defaultSvgLoader = config.module.rules.find(
      (rule) => typeof rule?.test?.test === "function" && rule.test.test(".svg")
    );
    console.log(defaultSvgLoader);
}
  1. Added resourceQuery: { not: [/svgr/] } into the logged output object so that *.svg?svgr paths will be ignored