Load SVG’s from different “Domains / Ports / Protocols”

TL’DR: You can’t (Just some workarounds).

I’m currently working on a project, and there was a need to load SVG images to the page. We thought like, ok, not a big deal, the tag SVG can help us doing that. Worst decision ever.

First, let me give you an example of what we tried to do:


<svg viewBox=”0 0 100 100">
    <use xlink:href=”/path/to/svg.svg"></use> 
</svg>

Just to keep in mind, our stack is React, Redux, es6, Webpack and c# for the backend.

So, this worked fine while we were in localhost and the SVG was loaded. Then, we started the integration with the backend ninja guys.

Well, after the integration was made, console errors started to popup:

Unsafe attempt to load URL URL/TO/SVG.svg. Domains, protocols and ports must match.

After some heavy research, like almost two days, we saw an article on chromium blog that talks about this stuff. Apparently, this is a security issue, because a SVG is a XML, and you can’t load a XML file from different locations.

Currently, we have the main project running in a domain and the other project in another domain, and the main project loads the second one. So, the requests are based on another port. This can also occur if you try to load from a cdn.

From developer Mozilla:

For security reasons, some browsers could apply a same-origin policy on use elements and could refuse to load a cross-origin URI within the xlink:href attribute.

How can you solve this?

Like I said before, you cant load SVG’s from different ports, protocols or domains.

Our approach was:
Ok, if we can’t load, we will start to copy and paste all the SVG’s to the DOM. After 3 seconds of thinking, we were like, HELL NO!!

What if we had a loader in webpack, whose job was taking the SVG and inlining it into the DOM? So we don’t have to do nothing? Well, this is not the best option, but, do we have anything better?
We used a thing called svg-inline-react, which inlines the SVG. That was our approach.

Implementation

First, we implemented the loader in webpack, like so:

{
    test: /\.svg$/,
    loader: 'svg-inline',
}

Then, we made a custom component that solely receives a prop and inlines the SVG.

import SVGInline from ‘svg-inline-react’;
export default Class Svg extends React.Component {
    render() {
        return <SVGInline role=”img” src={ newIcon } />;
    }
}

Example of usage:

import React from ‘react’;
import Svg from ‘../components/SvgInline’;
import Icon from ‘../icons/star.svg’;
<Svg icon={ Icon } />;

That’s about it! So the problem was loading SVG’s from different Port’s, and our approach was inlining it into the DOM. Not the best approach maybe, but it worked.