sensei
sensei copied to clipboard
SVG icon sprite not working when using a CDN
Steps to Reproduce
- Configure WordPress to load assets from an external CDN
- Open a course page frontend
- See that Sensei icons are missing, and there is a CORS error in the console
Security Error: Content at example.com may not load data from cdn.example.com/wp-content/plugins/sensei-lms/assets/dist/icons/sensei-sprite.svg?v=4.6.0.
Background
We package SVG icons at build time into one sprite file and use the SVG <use> element to pick icons from it:
<svg><use xlink:href=".../sensei-sprite.svg#sensei-sprite-name"></use></svg>'
It is currently not possible to set up cross-origin rules for this element: Understanding CORS and SVG
Solutions
Add CDN exception for the file
Ask users to configure their CDN or plugin to serve this file directly, so it's not loaded from an external server with a different URL and not blocked by the same-origin policy.
Load the file with JS
Since AJAX requests can contain the needed crossorigin attributes, we can
- Fetch the sprite file with a request in JS
- Append it to the document in a new
<svg>element - Icons can now be referenced only by id, since they are on the same page:
<svg><use xlink:href="#sensei-sprite-name"></use></svg>
Pros/cons:
⊕ SVG can still be cached ⊖ Might take a flash of time for the JS to run and load the sprite
Render the sprite with PHP
We can also output the sprite in the HTML when rendering the page.
Pros/cons:
⊕ Simpler ⊖ No caching, the svg icons are adding bytes to every page request ⊕ Can be optimized to only serve the icons used on the page ⊖ Might require change to the assets build process too to not merge the icons into one file