Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding react-svg-loader to webpack

Tags:

webpack

svg

I want to use react-svg-loader to import and use some svg assets I have for my app. You can find my webpack config below. The problem, however, is that I am also using some file loaders for svg files. These are needed because parts of my app are importing icons from font awesome, e.g. <i className="fa fa-lock" aria-hidden="true" />. So I can get the react-svg-loader working by stop having my file loader look for svg files, but then a lot of the icons on my app won't render. If I don't do this then my webpack will fail to build, saying things like:

ERROR in ./node_modules/font-awesome/scss/font-awesome.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/react-svg-loader/lib/loader.js):
NonErrorEmittedError: (Emitted value instead of an instance of Error) Error in parsing SVG: Non-whitespace before first tag.

So how can I resolve these two conflicts? Thanks.

const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");

const config = {
  entry: [
    "babel-polyfill",
    `${SRC_DIR}/app/index.js`,
    `${SRC_DIR}/app/assets/stylesheets/application.scss`,
    `${SRC_DIR}/app/components/index.scss`,
    "font-awesome/scss/font-awesome.scss",
    "react-datepicker/dist/react-datepicker.css",
    "rc-time-picker/assets/index.css",
    "react-circular-progressbar/dist/styles.css",
    "@trendmicro/react-toggle-switch/dist/react-toggle-switch.css",
  ],
  output: {
    path: `${DIST_DIR}/app/`,
    filename: "bundle.js",
    publicPath: "/app/"
  },
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: "babel-loader"
          },
          {
            loader: "react-svg-loader",
            options: {
              jsx: true
            }
          }
        ]
      },
      {
        enforce: "pre",
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
        options: {
          failOnWarning: false,
          failOnError: true
        }
      },
      {
        test: /\.js$/,
        include: SRC_DIR,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'stage-2']
        }
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      },
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: ['file-loader?context=src/images&name=images/[path][name].[ext]', {
          loader: 'image-webpack-loader',
          query: {
            mozjpeg: {
              progressive: true,
            },
            gifsicle: {
              interlaced: false,
            },
            optipng: {
              optimizationLevel: 7,
            },
            pngquant: {
              quality: '75-90',
              speed: 3,
            },
          },
        }],
        exclude: path.resolve(__dirname, "node_modules"),
        include: __dirname,
      },
      {
        test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        // loader: "url?limit=10000"
        use: "url-loader"
      },
      {
        test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
        use: 'file-loader'
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "application.css"
    }),
  ]
};

module.exports = config;
like image 276
Jimmy Avatar asked Oct 18 '18 20:10

Jimmy


People also ask

How install SVG with React and webpack?

Once you start your application, Webpack will do its thing and you don't need to worry about your SVGs anymore. You can put your SVG files anywhere in your src/ folder and import them wherever you need them as React components. This method is generally referred to as inline-svg .

How add SVG in React?

There are a few ways to use an SVG in a React app: Use it as a regular image. Import it as a component via bundler magic (SVGR) Include it directly as JSX.

What is SVG React loader?

A webpack loader allowing for inline usage of a SVG as a React component, or for composing individual SVGs into larger ones. The latest version has been refactored to allow for receiving an SVG/XML string or an JSON.

How do I export React components from SVG to Webpack?

When there is already any other loader using default export for svg files, @svgr/webpack will always export the React component via named export. If you prefer named export in any case, you may set the exportType option to named. By default, @svgr/webpack includes a babel-loader with an optimized configuration.

What is the SVGA Webpack loader?

A webpack loader allowing for inline usage of a SVG as a React component, or for composing individual SVGs into larger ones. The latest version has been refactored to allow for receiving an SVG/XML string or an JSON object-tree representing an SVG.

How to integrate SVG files with 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.

Is there a lightweight alternative to svgr in react?

A lightweight alternative solution to svgr is react-svg-loader. For the most part, we do not want all our SVG files to be loaded as a React components. We could combine the above methods depending on the use case. All we have to do is update our webpack configuration.


1 Answers

I had similar issues, while trying to load SVG's with react-svg-loader, but Font Awesome SVG's with file-loader. This was the config that I used to solve that problem:

  {
    test: /\.svg$/,
    exclude: path.resolve(__dirname, 'node_modules', 'font-awesome'),
    use: ['babel-loader', 'react-svg-loader'],
  },
  {
    test: /\.svg$/,
    include: path.resolve(__dirname, 'node_modules', 'font-awesome'),
    use: [{
      loader: 'file-loader',
      options: {
        jsx: true,
      },
    }],
  },

If your webpack config is not in the root, correct the exclude/include paths accordingly!

Note that you have multiple rules for SVG's in your webpack config, play with include/excludes to make them all work for your case.

like image 192
samikarj Avatar answered Oct 22 '22 20:10

samikarj