DEV Community

Cover image for How To Integrate SVG For Website And React App With Webpack
Antoine Amara
Antoine Amara

Posted on

How To Integrate SVG For Website And React App With Webpack

In this post, we will see how to use SVG images in a website and React app. We'll learn how to integrate, simplify, optimize and automate the use of SVG with Webpack.

What is SVG

Scalable Vector Graphics is an XML-based vector image format. It's an open format supported by the W3C. All modern browsers (Firefox, Chrome, Opera, Safari, Edge) have SVG rendering support. W3C create this format for websites a few years ago. Let's take a look at some advantages of SVG:

  • Scalability and resolution: this is the main advantage. It doesn't use pixels but vector computation, so the image is scalable and is adapted to all screen resolutions.
  • High performance: the SVG format is light and, the browser can render it fast.
  • DOM styling: the SVG can be inline to the HTML. So, CSS can style it, and javascript can manipulate it as a DOM element.

HTML5 and the SVG format

State of the support of SVG format

SVG stable version is the SVG 1.1-second edition. Almost all browsers have great support for SVG rendering. Note, the specification is not trivial, and browsers don't implement all specs. For more details about SVG 1.1 browser support, see caniuse.com.

Antoine AMARA SVG Webpak Integration Blog Post SVG Website Support

After this introduction, let's see how to load SVG.

How to load SVG as an image

The IMG tag can load the SVG as an image. With an IMG tag, the image is not vectorial anymore, and the advantage of scalability is lost.

index.html

<body>
  <img src="img/example.svg" />
</body>
Enter fullscreen mode Exit fullscreen mode

How to inline SVG

Another way to display an SVG is to inline the XML directly into the HTML file. It's the better way to use SVG because the browser will compute the vectors and keep all advantages of it.

index.html

  <body>
    <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 100px 100px">
      <circle r="50px" cx="50px" cy="50px" fill="#08415c" />
    </svg>
  </body>
Enter fullscreen mode Exit fullscreen mode

We have seen how to manually add SVG images into a static website. The aim is now to automate this operation with Webpack.

Website integration through Webpack

Almost every website and web app use Webpack as a bundler to apply some operations on the assets. An easy way to make the SVG integration is to use a Webpack plugin to automatically inline the SVG files' content to the bundled HTML.

Let's use html-webpack-plugin to manage the HTML files as a template with Webpack. We can use html-webpack-inline-svg-plugin in addition to this one to manage SVG into our HTML template. This plugin can easily inline some SVG's to HTML files by simply using an IMG tag with an "inline" attribute.

Let's install these plugins:

shell

# NPM
npm install --save-dev html-webpack-plugin html-webpack-inline-svg-plugin
# Or Yarn
yarn add -D html-webpack-plugin html-webpack-inline-svg-plugin
Enter fullscreen mode Exit fullscreen mode

Now, add some configurations to manage HTML and SVG, add it to webpack.js (or webpack.comon.js if you split the configurations into multiple files).

webpack.common.js

...otherImports
import HtmlWebpackPlugin from "html-webpack-plugin";
import HtmlWebpackInlineSVGPlugin from "html-webpack-inline-svg-plugin";

module.exports = {
  ...otherWebpackConfigs,
  plugins: {
    ...otherPluginsConfigs,
    new HtmlWebpackPlugin({
      filename: "index.html",
      template: "src/index.html",
      chunks: ["main"]
    }),
    new HtmlWebpackInlineSVGPlugin({
      runPreEmit: true,
    }),
  },
};
Enter fullscreen mode Exit fullscreen mode

To inline an SVG, you have to use the IMG HTML tag and add an inline attribute. Webpack will replace the tag and inline the XML from the file.

index.html

<body>
  <img inline src="src/img/logo.svg">
</body>
Enter fullscreen mode Exit fullscreen mode

Note: the image path is a relative path from the project root. It's because I add src/img/ and not img/.

We know how to integrate SVG into a static website. Now, let's see what to do if we use React to construct the frontend.

React app integration

How to integrate SVG with create-react-app

create-react-app is the easiest way to init a React application. It comes with some Webpack configurations.
The first way to load an SVG is to import the file to your component and load it as an image.

App.js

import logo from "./img/logo.svg";

const App = () => {
  return <div>
    <img src={logo} alt="Logo" />
  </div>
}
Enter fullscreen mode Exit fullscreen mode

Or to directly inline the XML into the JSX:

App.js

const App = () => {
  return <div>
    <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 100px 100px">
      <circle r="50px" cx="50px" cy="50px" fill="#08415c" />
    </svg>
  </div>
}
Enter fullscreen mode Exit fullscreen mode

But, react-script (the component used by create-react-app) can use the Svgr plugin to convert the imported SVG as a component. The created React component will inline the XML from the SVG file inside the DOM.

App.js

import { ReactComponent as Circle } from "./img/circle.svg";

const App = () => {
  return <div>
    <Circle />
  </div>
}
Enter fullscreen mode Exit fullscreen mode

Now, we can use SVG with create-react-app, but it is interesting to know more about the configuration of Webpack to convert an SVG image to React component.
Let's see how to integrate SVG with a custom Webpack configuration for React application.

How to integrate SVG with a custom webpack configuration

We have seen react-scripts use the Svgr plugin to create React component for inlining SGVs in the DOM.
Let's deep dive into the Svgr configuration with Webpack:

First, install the Svgr webpack plugin:

shell

# npm
npm install --dev @svgr/webpack
# or with yarn
yarn add -D @svgr/webpack
Enter fullscreen mode Exit fullscreen mode

Next, let's configure Webpack:

webpack.common.js

module.exports = {
  ...otherWebpackConfigs,
  module: {
    rules: [
      ...otherAssetsRules,
      // intercept images format
      {
        test: /\.(png|jp(e*)g)$/,
        use: [{
          loader: "url-loader",
          options: { ...loaderOptions  }
        }]
      },
      // intercept svg and use svgr to convert them to React Components
      {
        test: /\.svg/',
        use: ["@svgr/webpack"],
      },
    ],
  },
};
Enter fullscreen mode Exit fullscreen mode

Finally, let's import and easily inline an SVG into a component:

App.js

import Circle from "./img/circle.svg";

const App = () => {
    return <div>
      <Circle />
    </div>
}
Enter fullscreen mode Exit fullscreen mode

Now, we can use SVG in a website and React app. The last step is to optimize SVG to load it quickly.

How to optimize SVG contents

SVG files can contain redundant and useless information, especially when they are created with an editor. We can safely remove the useless information from the XML. SVGO (SVG Optimizer) is here to automate these operations.

Note: the html-inline-svg-plugin already uses SVGO to optimize SVG before inlining them into the HTML.

Install SVGO cli:

shell

# NPM
npm install -g svgo
# Or Yarn
yarn global add svgo
Enter fullscreen mode Exit fullscreen mode

To optimize one SVG:

shell

svgo img/test.svg
Enter fullscreen mode Exit fullscreen mode

To optimize all SVG files within a directory:

shell

svgo -f ./img
Enter fullscreen mode Exit fullscreen mode

Automate SVG optimization with webpack

Webpack can use SVGO with svgo-loader:

Install the loader:

shell

# NPM
npm install -D svgo-loader
# Or Yarn
yarn add -D svgo-loader
Enter fullscreen mode Exit fullscreen mode

Add the loader to Webpack configurations:

webpack.comon.js

module.exports = {
  ...otherWebpackConfigs,
  module: {
    rules: [
      ...otherAssetsRules
      {
        test: /\.svg/,
        use: [...otherLoadersForSVG, 'svgo-loader'],
      },
    ],
  },
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

W3C creates SVG for the web and, it is good to display a logo, to use some icons or illustrations for a website or a web application. Webpack can easily handle SVG optimization and inlining for complete integration to web apps.

Finally, this article presents the integration for Webpack but, some alternative exists for other bundlers (parcel, ...) and other UI frameworks (VueJS, AngularJS, ...).

Discussion (0)