Search code examples
reactjssvgbabeljs

How can I use babel to transpile SVGs into React components?


I am using Create React App to build a component library. In some of my components, I import SVGs like this:

import { ReactComponent as IconClear } from 'icons/clear.svg';

This works in development, as I know CRA has support for SVGs like this.

I am using @babel/cli to transpile my src/lib folder into a dist folder to use the library as a node package:

rm -rf dist && NODE_ENV=production babel src/lib --out-dir dist --copy-files

In production, these SVG components don't work. I get the error:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

How can I use babel to transpile these SVGs into components? I don't want to manually have to create components for each SVG and I want to keep the SVG markup intact, so it can still be opened in design software. Is there a babel preset / plugin that can do this?


Solution

  • I was able to accomplish what I needed using the babel-plugin-inline-react-svg package.

    I simply installed it: npm install babel-plugin-inline-react-svg --save-dev

    Then I added it as a plugin in my babel.config.json.

    "plugins": ["inline-react-svg"]
    

    Now when I run my build script, the SVGs are inlined.

    The source code:

    import { ReactComponent as IconClear } from 'icons/clear.svg';
    

    ...is transpiled into:

    var IconClear = function IconClear(props) {
      return /*#__PURE__*/_react.default.createElement("svg", props, /*#__PURE__*/_react.default.createElement("path", {
        d: "M12.59 0 14 1.41 8.41 7 14 12.59 12.59 14 7 8.41 1.41 14 0 12.59 5.59 7 0 1.41 1.41 0 7 5.59z"
      }));
    };
    

    SVGs now work in production without any errors.