I'm using rollup to bundle a react npm package that contains an icon component that takes a name as a prop and returns an Icon with that name wrapped by a react component. This is the component code:
import sprite from './public/sprite.svg';
function Icon({ name }) {
return <svg className="svg-wrapper">
<use href={`${sprite}#${name}`} />
</svg>
);
}
The folder structure is the following:
- src
- - public
- - - sprite.svg
- - icons
- - - some-icon.svg
- - - some-other-icon.svg
- - index.tsx # component with the code mentioned above
And this is my rollup config:
export default {
plugins: [
esbuild({
sourceMap: false,
target: "esnext"
}),
image(),
svgicons({
inputFolder: "src/icons",
output: "public/sprite.svg"
}),
json()
]
}
This works fine in Chrome (although it does inline all the svg inside of the href
which I think it's the purpose of this approach) but in Safari it triggers the following error:
Unsafe attempt to load URL data:image/svg+xml,%3c%3fxm ....
Domains, protocols and ports must match.
The thing is, as mentioned, this is an npm package that packages the icons as part of the js bundle (inlining) so there's not much control over how this component is served since this is handled by the browser caching (also one of the key points of using this approach). I'm quite familiar with CORS and I know that perhaps avoiding to use data:image/svg+xml
uri links would fix this but would increase the complexity of the build steps of this package (needing to build the icons using svgr/svgo and then have some kind of lookup table to give back the right icon based on the name prop i.e.).
So, ultimately my question is, with the sprite approach in a react component library is there a foolproof way of avoiding these kind of issues and cross-browser inconsistencies? Thanks in advance for any help provided.