In the quest for smaller and smaller zip files, one important tool is eliminating extra files altogether. Every file in the zip has an overhead of around 88 bytes - more depending on the length of the filename. This is a significant cost, and it’s one reason a sprite sheet is so valuable (crunching all your PNGs into one PNG, for example).
Let’s ignore images for a second, though, and think about just our core files - in a typical
game, this is your index.html
, your .css
file, and your .js
file.
1 |
|
1 |
|
1 |
|
We’ll tie all this together with our gulp build:
1 |
|
So, we seem to have the basics down - we’re minifying all our source files and dumping them into a folder. Let’s add a zip step, using advzip to crush the output zip file even further, and add some size lines so we can get measurements:
1 |
|
And the build:
1 |
|
Well, in this case the zip file is actually bigger than the source files, but that’s to be expected with our tiny example files (the per-file overhead is bigger than our actual content). Let’s see how we can reduce it.
Inlining our CSS
You might be wondering why we’re bothering with CSS at all; for a canvas-heavy game, you may be able to ignore it altogether. Not every game is based on canvas, though, and if you make use of CSS animations and HTML elements, you might actually have quite a bit of CSS to manage.
Let’s start with the obvious: discard the CSS file, and insert the content inline into our HTML.
1 |
|
In HTML5, the type=text/css
attribute is now optional, so let’s just get rid of it.
1 |
|
Last, since we’re cutting out our cleancss
step, we want to make sure the inline CSS
will be minified. Luckily the htmlmin
plugin provides an option for exactly that:
1 |
|
Build!
1 |
|
Looking good, that’s 124 bytes off the top. This is kind of a sad trade-off if your game uses
a lot of CSS, though: inlining all that CSS is uglier to work with, prevents you from calling
cleancss
with your own custom options, and doesn’t let you use plugins like gulp-sass
.
A potential solution is to rearrange our build to keep the CSS content in its own file, but
then insert it into the finished HTML, using gulp-template
.
1 |
|
You’ll notice the new ERB/JSP-style “tag” here, a placeholder for our CSS content. Let’s update
our gulpfile to process our CSS files first, placing them in a temporary location, which we can
then read in using the standard fs
module.
1 |
|
Running this build produces the exact same size, but now we can organize our CSS content however we wish, including additional style-related plugins.
Inlining our Javascript
Now that we’ve done it for CSS, it seems pretty obvious: why not do it for our game code? We’re already minifying it into an unreadable ball, we might as well insert it into the HTML as well.
In past iterations of HTML/XHTML, you may have worried about encoding characters you’d encounter
within your source code. In HTML5, the only magic string you need to worry about is </script>
.
It’s very unlikely you have the string </script>
anywhere in your game logic, so feel free to
insert as much JavaScript as you want.
1 |
|
Don’t forget to update the gulpfile to run both CSS and JS before the HTML step.
1 |
|
And, build!
1 |
|
Again, another 105 bytes off the top.
Optimizing our HTML
We’re down to a single HTML file, so there’s not much more we can do, except take a look at the HTML itself. Our HTML is pretty simple, but since this is HTML5 and we’re running in modern browsers, pretty much every one of these tags is optional (or, more accurately, the browser is smart enough to insert them itself, in the right place in the DOM, if they’re missing).
Let’s go ahead and cut the <html>
, and the <body>
too. And the <head>
. And, since
text/javascript
is the default script type in HTML5, let’s cut that too! That leaves us
with the following HTML page.
1 |
|
And build:
1 |
|
There you have it. We’ve managed to crush our final zip file size from the original 484 bytes down to 222 bytes, a savings of 262 bytes of overhead.
Note that we express this savings in terms of bytes of overhead, and not a percentage. For our silly example, this was a savings of ~45%, but that’s not relevant because these space savings won’t scale as we add the actual game logic - it’ll stay roughly 262 bytes off the top. So, you can probably save this type of optimization for very late in the process, when you’re trying to cram that last sprite into your game.
Using existing plugins
Gulp has a great plugin ecosystem, so chances are if you’re trying to do something, someone has already written a plugin for it. The functionality we wrote into our gulpfile above can actually be accomplished out-of-the-box with the gulp-inline-source plugin.
Using the plugin, our HTML would look like this.
1 |
|
The plugin then automatically finds those files in your gulp sources and inserts them as appropriate. For most cases, this should give you everything you need! If you want exact control of the final output, though, then the template approach we developed above is ideal.