stewartlord/identicon.js

Probably don't want base64 svg

Closed this issue · 11 comments

@stewartlord Just looking to cut down on memory footprint here, is there any way to not have a base64 version for SVG? According to Chris Coyier here: https://css-tricks.com/probably-dont-base64-svg/ we don't need to base64 svg, unnecessarily comes out 133% bigger.

Is it currently possible to generate just SVG? Tried browsing around the source and using .render() instead of .toString() -- since I see .toString() is just .render().getBase64() -- but that did not work.

Heya, yes this should be possible. Let me see if I can get it to work here.

It can be done, but you have to escape quotes which ends up making the string larger than if it's just base-64 encoded. For example:

 960 - original
1280 - base64  (+33%)
1690 - escaped (+76%)

@stewartlord Why do quotes have to be escaped? Can't use single quotes or no quotes? For instance, <img id=foo src=http://www.google.com/favicon.ico /> is valid HTML, another example with SVG. Just looking for a SVG string, looks like it exists and then btoa is called on it. Not too sure why that has to be escaped? Especially if you are base64 encoding it.

...
        getBase64: function(){
            var i,
                xml,
                rect,
                fg     = this.foreground,
                bg     = this.background,
                stroke = this.size * 0.005;

            xml = '<svg xmlns="http://www.w3.org/2000/svg"'
                + ' width="' + this.size + '" height="' + this.size + '"'
                + ' style="background-color:' + bg + ';">'
                + '<g style="fill:' + fg + '; stroke:' + fg + '; stroke-width:' + stroke + ';">';

            for (i = 0; i < this.rectangles.length; i++) {
                rect = this.rectangles[i];
                if (rect.color == bg) continue;
                xml += '<rect '
                    + ' x="'      + rect.x + '"'
                    + ' y="'      + rect.y + '"'
                    + ' width="'  + rect.w + '"'
                    + ' height="' + rect.h + '"'
                    + '/>';
            }

            xml += '</g></svg>';

            return btoa(xml);
        }
...

So if instead this was broken down into something like getSVG (same as above no btoa) and getBase64 (btoa on getSVG).

(p.s. Use your lib on Pholder in case you're wondering where your code ends up, thanks for this lib!)

You could use single quotes but that relies on the src attribute being double-quoted. Since this library doesn't write the image tag it seems preferable to produce a data URI that works regardless of how the tag is crafted. Base 64 seems the safest.

Do you have numbers that show a measurable performance difference when the data URI is smaller?

@stewartlord Using numbers above

 960 - original (<-- assume this is svg element?)
1280 - base64  (+33%)

If server side rendered on pholder.com, max 400 images with 400 authors so difference of (napkin maths):

1280 - 960 = 320 size diff * 400 author pics = 128,000 chars / 1024 bytes in a kilobyte = 125k?

Scenario may be extreme, lets say there is half that on a forum like site on a conversation heavy thread? Imagining half that.. so 62.5k saved from download size if first rendered serverside? Unless I am thinking about this wrong.

Your math looks right to me. Is rendering server-side a common case though?

@stewartlord Google image search embeds thumbnails via server-side render (SSR) as base64 both for UX (image content on first animation frame) and to cut down on requests. Later is less relevant because images are generated via an algorithm but the first is not. There is a trend to SSR embed small images, thumbnails, and icons.

SSR also allows the images to be cached as a part of the HTML, so if a user navigates forward to another page and then hits the back button those SSR embedded images do not have to be re-rendered on the client which would first paint an empty image until the identicon.js render could fire (similar to flash of unstyled content [fouc] with CSS).

Cool, reopening this. Thanks for the PR :)

@stewartlord Has this been published to npm?

Just did it about an hour ago 👍🏻

@stewartlord Cool thing about this is you don't even need to put it in an img element attribute or as a style background. Can just use the svg element outright. 👍 Perf gain is real, wish I had time to pull some stats but can see it when scrolling on a large page. Browsers like elements and svg paint times are FAST. Cheers! :D