'how to load Svg components in remix run application

I have some Svg files which i want to load as react components in remix run app. for example in create-react-app your could do something like this


import { ReactComponent as Logo } from './logo.svg';
function App() {
  return (
    <div>
      {/* Logo is an actual React component */}
      <Logo />
    </div>
  );
}

is there any similar way in remix-run do achieve the same ?



Solution 1:[1]

Unfortunately there is no way currently to import an SVG file in your component file directly like in create react app.

And maintainers do not allow currently manipulating the esbuild config to add features like that via plugins (cf. the discussion in this merge request).

If you don't need to style your SVG, you could simply put it in the public/ folder and include it with an img element in your component.

Smaller JS bundles, faster page hydration, and immutable .svg's over the network that are only ever downloaded once. (cf. this message)

function App() {
  return (
    <div>
      <img src="/logo.svg" alt="My logo" />
    </div>
  );
}

You could also create yourself a JSX component and put your SVG code inside it (with some manual conversion for prop names), or even put your SVG file in a folder, and use an external automatic conversion tool like SVGR to generate optimized JSX component from it with a simple CLI command.

In that case you have a component that you can import like any other component:

import Logo from './Logo.svg';
function App() {
  return (
    <div>
      <Logo />
    </div>
  );
}

Solution 2:[2]

For me, it only worked by creating a component with the SVG tag and then importing it

const HomeLogo = () => {
  return (
    <div>
        <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
            <g fill="none" fill-rule="evenodd">
            <circle cx="24" cy="24" r="24" fill="#FFF"/>
            <path fill="#0B0D17" d="M24 0c0 16-8 24-24 24 15.718.114 23.718 8.114 24 24 0-16 8-24 24-24-16 0-24-8-24-24z"/>
            </g>
        </svg>
    </div>
  )
}

export default HomeLogo

Solution 3:[3]

I created a workflow to convert the icons to react components in development using svgr and npm-watch. For good measure you will probably want to run the icons script before building for production too.

Install dependencies:

npm install -D @svgr/cli @svgr/plugin-svgo @svgr/plugin-jsx @svgr/plugin-prettier npm-watch npm-run-all

Update package.json scripts:

{
  //...
  "scripts": {
    //...

    // task to convert icons to components
    "icons": "npx @svgr/cli --out-dir app/icons -- ./icons",

    // watch task
    "icons:watch": "npm-watch icons",

    // compile once and start watching for changes
    "dev:svg": "run-s icons icons:watch",

    // remix dev
    "dev:remix": "remix dev",

    // run all dev: scripts including `dev:svg` (depending on the remix template you might neet to replace the default `dev` script)
    "dev": "run-p dev:*"
  },
  // npm-watch configuration
  "watch": {
    "icons": {
      "patterns": [
        "icons"
      ],
      "extensions": "svg",
      "quiet": false
    }
  },
  //...
}

The svg icon files are located in the project root in icons/ and the react components are generated in the app/icons/ folder.

svgr.config.js (optional)

module.exports = {
  plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx", "@svgr/plugin-prettier"],
  typescript: true, // optional
};

svgo.config.js

module.exports = {
  plugins: [
    {
      name: "preset-default",
      params: {
        overrides: {
          removeViewBox: false,
        },
      },
    },
  ],
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Fabricio Cunha
Solution 3