We have used a large number of image resources in our project, most of which are ICONS composed of simple lines. These materials are built as vector images from the beginning of the UI design, making them ideal for storing in vector files like SVG. At present, iOS and Android (with Google Play) all use Slicing technology, which can automatically choose the right image materials into the bag according to different devices. The resource management function of Flutter can automatically select the right image resources according to different screen resolutions and densities. However, Flutter cannot automatically deliver different sizes of resources according to different devices like The Apple Slide. Therefore, multiple sets of materials will undoubtedly put a significant pressure on App package size.

We randomly selected an icon for testing:

Resource Format x1 x2 x3 Total
PNG 536 bytes 908 bytes 1321 KB 2765 bytes
SVG 1896 bytes

We found that, thanks to the nature of vector images, THE SVG format does not need to generate a set of bitmaps for every resolution like PNG does, so it only needs to calculate the size of a file, and SVG has a definite advantage in disk footprint. And that’s on top of a maximum resolution of X3. With the popularity of ultra-high resolution screens and cross-platform development frameworks (Flutter, SwiftUI), the cost of cutting one image for each device is only going to get higher.

PNG also supports lossy compression, so we typically compress PNG further to squeeze the size of the App. But what many people may not know is that the SVG format can also be compressed.

When we open the SVG shown above with a text editor, we find that it uses XML as the description language and describes vector graphics based on a two-dimensional coordinate system. His head tends to contain unwanted information, including redundant information left over from conversion software. Also, like JS compression, we can further compress the file size by removing formatting.

<? xml version="1.0" encoding="UTF-8" standalone="no"? > <! DOCTYPE svg PUBLIC"- / / / / W3C DTD SVG 1.1 / / EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24pt" height="24pt" viewBox=24 24 "0 0">
<g enable-background="new">
<clipPath id="cp0">
<path transform="The matrix (0, 1, 1,0,24)" d="M 0 24 L 24 24 L 24 0 L 0 0 L 0 24 Z " fill-rule="evenodd"/>
</clipPath>
<g clip-path="url(#cp0)">
<clipPath id="cp1">
<path transform="The matrix (0, 1, 1,0,24)" d="M -335 -613 L 40 -613 L 40 54 L -335 54 Z "/>
</clipPath>
<g clip-path="url(#cp1)">
<path transform="The matrix (0, 1, 1,0,24)" d="M -5 29 L 29 29 L 29 -5 L -5 -5 Z " fill="#ffffff" fill-opacity=". 01"/>
</g>
</g>
<clipPath id="cp2">
<path transform="The matrix (0, 1, 1,0,24)" d="M -335 -613 L 40 -613 L 40 54 L -335 54 Z "/>
</clipPath>
<g clip-path="url(#cp2)">
<path transform="Matrix (1,0,0,1,3.5, 20.75)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke="#1f2329" d="M 0 .25 L 18 .25 "/>
</g>
<clipPath id="cp3">
<path transform="The matrix (0, 1, 1,0,24)" d="M 5.5 10.64008l 5.5 7 L 9.158594 7 L 19.5 17.3459l 15.84753 21 L 5.5 10.64008z"/>
</clipPath>
<g clip-path="url(#cp3)">
<clipPath id="cp4">
<path transform="The matrix (0, 1, 1,0,24)" d="M -335 -613 L 40 -613 L 40 54 L -335 54 Z "/>
</clipPath>
<g clip-path="url(#cp4)">
<path transform="The matrix (0, 1, 1,0,24)" d="M.5 25 L 25 25 L.5 2 Z" fill="#ffffff"/>
</g>
</g>
<clipPath id="cp5">
<path transform="The matrix (0, 1, 1,0,24)" d="M -335 -613 L 40 -613 L 40 54 L -335 54 Z "/>
</clipPath>
<g clip-path="url(#cp5)">
<path transform=,0,0,1,5.5 "matrix (1, 3)" stroke-width="2" stroke-linecap="butt" stroke-linejoin="round" fill="none" stroke="#1f2329" d="M 0 10.35992 L 0 14 L 0 10.35992 Z"/>
</g>
</g>
</svg>
Copy the code

We used the SVG optimization tool, and after compression, we can see that the number of characters is significantly reduced, and the compression ratio is up to 22%. Although the principle is not very complicated, but the actual compression effect is still very considerable.

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox=24 24 "0 0"><path fill="#fff" fill-opacity=". 01" d="M0 0h24v24H0z"/><path d="M3.5 h18 21" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke="#1f2329" stroke-miterlimit="10"/><path d="M5.5 13.36V17h3.66L19.5 6.652 15.848 3zm0 0" fill="none" stroke-width="2" stroke-linejoin="round" stroke="#1f2329" stroke-miterlimit="10"/></svg>
Copy the code
Resource Format x1 x2 x3 Total
PNG 326 bytes 654 bytes 567 KB 1547 bytes
SVG 431 bytes

When you compress both formats individually, the final volume difference is not significant. Especially for native platforms like iOS or Android (with Google Play) that support slicing, bitmap size is better than vector graphics. In addition, bitmaps have a lower cost of parsing time than vector maps (especially on complex images). There are additional PNG optimizations for iOS, so Apple has not officially supported SVG resources until now. However, in the latest Xcode 12 we were surprised to find that Assets already support SVG resources.

This is a painless feature that can be implemented in previous versions of Xcode via a split-by-split-curve approach, and it is also possible to parse SVG directly through CoreSVG using a proprietary API, although this is not recommended and may be rejected. Although Apple has presented the Symbol Image scheme last year, which is essentially a collection of SVG paths and allows designers to design custom ICONS through SF Symbols App, the cost of learning may not be within the reach of every designer.

This is somewhat disappointing, as Android next door already supports SVG resources (albeit in a neutered form), and our internal Flutter project uses SVG early on. I suspect Apple is not quite sure about SVG yet, given that SVG is a 20 year old format with all the historical compatibility baggage, animation, performance, and so on. Apple has a very strong control over their SF Symbols, which can guarantee 100% compatibility and performance. But can you guarantee that your UI is implemented in strict accordance with the specification when drawing ICONS? It’s probably worse than you think.

Taking our Flutter project as an example, we found that a large number of ICONS were not drawn in strict accordance with the outline, but were implemented in ways such as path overlay. These problems not only increase the size of SVG files, but also increase the complexity of converting vector data into position diagrams. However, according to our Flutter tests, the current mainstream models do not have much parsing pressure for simple ICONS.

Here’s a list of possible problems with the SVG format:

  1. As compression technologies evolve, bitmap formats (PNG, WebP, HEIF) will get smaller and smaller, closing the gap with SVG.
  2. The benefits of converting complex images to SVG are small or even lower, especially in terms of parsing speed.
  3. High-quality SVG resources are built on specification construction, and non-standard SVG is larger and less efficient to parse.
  4. Currently, SVG parsing libraries on different platforms have some compatibility issues, and in addition to some complex effects, they do not support animation and other features. We won’t be able to use SVG on iOS yet, but we believe that vector resources will become a mainstream format with the development of cross-platform, ultra-high resolution and other technologies. Let’s wait and see.

Reference:

  1. Vector Graphics solutions for iOS (SVG)
  2. Introduction to and initial experience with SVGo, the SVG compact compression tool
  3. SVG optimization Tool