SVG: The Hard Parts — I
Why Use SVGs
- SVGs have a smaller size to resolution ratio as compared to their raster counterparts meaning scale without pixilation.
- SVGs can be animated using css by adding styles individual tags like <path/> ,<line/>, <circle/> etc.
- SVGs are reusable, changing the style of individual tags is as easy as writing css.
Why Bundle SVGs?
As you can see in the Codepen example. The definition of the SVG is written in the javascript window. This also means that using SVGs in this manner leads to padding your Javascript files with SVG.
While important components of a webpage, SVGs, for most use cases aren’t required to be displayed till after the page is interactive. Hence they should not be packaged with javascript that is required for business logic and painting the page.
Bundling assets reduces the number of HTTP calls being made this frees up the browser to make other calls, which is important because most popular browsers can make about six calls concurrently per hostname.
The usual method for separating SVGs into their own chunks is by bundling all SVGs together and creating sprites. Webpack has an excellent loader with 1.2k stars, SVG Sprite Loader, which can create a sprite for all SVGs in a route.
How are the Sprites formed?
During the project build process, sprite-loader has access to all components in a route, it identifies the SVG’s used by the component at a particular route and bundles all the SVGs into a single sprite. The Sprite that is formed as such is just another SVG file that has multiple SVG’s defined inside of itself.
A sprite typically has the following structure:
So for the various routes on the mobile-Web site, say Homepage, there would now be a network call to the sprite for that route which contains all the SVG’s for the Homepage component.
Have we found the perfect solution?
Well, not exactly. There are some caveats that need to be mentioned.
- CSS does not apply to SVGs bundled as Sprites. This is because the loader fundamentally changes the structure of the SVG. This makes reusing SVGs next to impossible.
- No control over when to fetch sprite bundles. SVGs should be fetched after more important assets have finished loading.
- For a given route, there are additional network calls to the SVG-sprites of the other routes of the site.
Additional network calls!!! Why did that happen?
This phenomenon occurs due to the logic that is built right into the svg-sprite-loader package when it comes to creating the SVG-sprites for any given route.
“The sprite-loader identifies all the SVGs referenced by a route level component and its children and then bundles them up into a sprite such that any SVG common between multiple route-level components is resolved into exactly one component’s sprite only which is the last one referencing it in the app routes.”
As a result, when any such common SVG is referenced inside of components whose sprites it wasn’t resolved into, the entire sprite in which the common SVG was resolved, is fetched. Hence, the additional network calls!
Is There A Better Solution?
A better solution should fulfil the following criteria:
- SVGs should be reusable. At the minimum they should be scalable and their colour schemes variable.
- Only the SVGs required to be displayed are should be present in the bundle.
- When SVG Bundles are fetched should be easily programable i.e it should be event driven.
In Part 2 we explore such a solution.
A lot of hard work and thinking and experimenting has gone into the development of this approach. This blog was possible due to contribution of Surbhi Arora, Vivek Rai, Nasir Bashir and the rest of the MWEB Team at FabHotels.