Mark James
Mark James

Reputation: 568

How to import SVG into Next.js component?

I am trying to import an SVG image from file into a Next.js component.

In the assets folder I have google.svg (icon):

<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>

I need to import that SVG inside of this inside of the Next.js component:

import googleLogo from '../assets/google.svg';

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}   // <---- import here icon
                </span>
                
              </div>
            </a>
          </Link>
        </div>
      </LoginLayout>
    );
  }
}

I installed this package: https://www.npmjs.com/package/next-images

and set configuration based on that documentation in next.config.js:

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

module.exports = withCSS(
  withSass({
    webpack: (config) => config,
    distDir: '../_next'
  }),
  withImages({
    exclude: path.resolve(__dirname, 'client/assets/svg'),
    webpack(config, options) {
      return config;
    }
  })
);

Why my import of SVG does not work?

Upvotes: 16

Views: 52191

Answers (5)

Om Bharti
Om Bharti

Reputation: 47

The Code:

webpack: (config, options) => {
    config.module.rules.push({
      test: /\.svg$/,
      use: [
        options.defaultLoaders.babel,
        {
          loader: "@svgr/webpack",
          options: {
            icon: true,
          },
        },
      ],
    });

    return config;
  },

Upvotes: 0

Lauris Kuznecovs
Lauris Kuznecovs

Reputation: 929

I got SVGs working with this next.js config.

next.config.js

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

    return config
  },
}

Upvotes: 3

justuff
justuff

Reputation: 238

I've recently added this myself. I followed the example on the Next.js repo.

https://github.com/zeit/next.js/tree/master/examples/svg-components

There's a couple of steps -

  1. You need to install the following dependency :
  • babel-plugin-inline-react-svg
  1. Inside your .babelrc you need to add the plugin babel-plugin-inline-react-svg
  "plugins": [
    "inline-react-svg",
  ]

You should then be able to import your SVG's into your components. Here's a gist of something similar I used it for.

https://gist.github.com/iamchristough/493c60112770058566d559e6860dc4c9

Note - you need to declare it as its own component <GoogleLogo /> if you just did {GoogleLogo} it will error. Also there is an issue with how babel transforms the SVG so any changes inside the SVG file won't appear. You need to rename the file in order for the bundler to see a change.

Upvotes: 9

ak85
ak85

Reputation: 4264

Another approach would be to make a component for your svg. I like this approach because I can easily pass in props for width, height color etc if required on the svg.

//GoogleLogo.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>
  );
}

and in your file from above.

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

Upvotes: 28

nullspace
nullspace

Reputation: 963

You can use @svgr/webpack plugin to convert svg imports to react component.

This will allow you to do the following:

import Icon from './icon.svg';

<Icon />

Upvotes: 11

Related Questions