oligofren
oligofren

Reputation: 22923

Unable to get `ReactComponent` export of @svgr/webpack

I am trying to get the same import statements going for both a Vite and Webpack setup (used by Storybook) and I am failing to get it to work for Webpack as advertised.

According to the docs for @svgs/webpack, version 5.5, this should work:

//  Does not work (undefined)
import {ReactComponent as UilPlus} from '@iconscout/unicons/svg/line/plus.svg'

But it does not. There is only the default export:

// Works
import UilPlus from '@iconscout/unicons/svg/line/plus.svg'

How can I fix this? I have even tried explicitly using the namedExport option, but it does not take effect.

Config:

      use: [
        {
          loader: '@svgr/webpack',
          options: {   namedExport: 'ReactComponent' }
        },
$ jq .version node_modules/\@svgr/webpack/package.json 
"5.5.0"

Upvotes: 2

Views: 4233

Answers (2)

Fan Yer
Fan Yer

Reputation: 393

As said in doc of @svgr/webpack, you should add url-loader or file-loader

https://github.com/gregberge/svgr/tree/main/packages/webpack

{
  test: /\.svg$/,
  use: ['@svgr/webpack', 'url-loader'],
}

then you can use it in your code

import starUrl, { ReactComponent as Star } from './star.svg'

const App = () => (
  <div>
    <img src={starUrl} alt="star" />
    <Star />
  </div>
)

Upvotes: 1

oligofren
oligofren

Reputation: 22923

After reading the source code for v5.5 of @svgr/webpack, @svgr/core and @svgr/babel-plugin-transform-svg-component and reading up on how loaders work, things finally made sense.

Turns out there was a crucial bit missing: the example showing use of ReactComponent has an extra loader added for the svg processing. I did not understand how a loader added later could affect something earlier. That was until I read the loader docs for Webpack 4 which explains how loaders are applied Right to Left.

Once that was out of the way, it was now clear that the svgr plugin somehow sees that the input it receives is from another loader and adjusts it behavior accordingly. That is exactly what happens in @svgr/webpack in line 32 to 41 and you can see the expected output in the snapshot test:

...
export default \\"data:image/svg+xml;base64,PD94bWwg..."
export { SvgIcon as ReactComponent };"```

The webpack module actually only does the detection and passes that info on to @svgr/core, whereas the core module is using babel-plugin-transform-svg-component to actually change the output based on the presence of a previous export.

Upvotes: 3

Related Questions