HTML5 better code size reduction

I’m trying to reduce the size of the .js output of a basic html5 build, but still ending up with huge .js filesizes ! , I’d really like to find out how i can reduce the output as much as possible.

I’ve updated today to Lime 2.6.9, openfl 3.3.9 , actuate 1.8.6, which is the latest build. I’ve created a brand new empty project. I’ve edited the main.hx so that all that the project does is trace “Hello World” (it doesn’t even import any libraries anymore or extend sprite); in the hope i can output the smallest possible .js file.

Main.hx now looks like this:

package;
class Main
{
    public function new() 
    {
        trace("hello World");
    }
}

Choosing Debug and html5 in flashdevelop produces a .js output which is a whopping 1371 KB !. (strangely choosing release gives the same filesize)

I’ve spent a couple of hours playing with the Dead Code Elimination , js-flatten, and minify compiler options etc. some of which reduce the output file size, (trying -final causes an error, unless -minify is also used? ) the best results i found having tried many manu combinations where

adding dce full to the project.xml file

<haxeflag name="-dce full" />

which bring the output .js size down to a still huge 537KB

and also using the compile line to compile with -minify -yui (where performancetest is my project name)

openfl build html5 -Dperformancetest -minify -yui

which brings the output size down further to a still huge 305KB ! which is still massive.

From what i can see, both of these create the 1371KB file first, then work a little magic on it to reduce the size, which whilst it does reduce the size a bit, still leaves it massively larger than it needs to be.

I’m stuck as to where i can go next to reduce the size further , Help !

Edit : over here it talks about BunnyMark being reduced to 22KB ?
http://www.openfl.org/blog/2014/03/18/flash-and-html5/

Could you try openfl test html5 -final?

I did try using -final , it was amungst my tests, (as briefly mentioned above),

openfl build html5 -Dperformancetest -final

fails with an error (although it does leave a 537KB .js file behind, which appears the same as the dead code elimination test i tried earlier)

if i use -final in conjunction with -minify i.e. either of

openfl build html5 -Dperformancetest -final -minify -yui
openfl build html5 -Dperformancetest -minify -yui -final

neither error, both leave the same 304KB .js file , (the same size as adding “dce full” to the project.xml, and compiling with just “-minify -yui” )

the -final error i receive is below, although i can’t see how it should be reducing the code further ?

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/google/javascript/jscomp/CommandLineRunner : Unsupported major.minor version 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: com.google.javascript.jscomp.CommandLineRunner. Program will exit.

It sounds like there is an error that is preventing Google Closure from running. Perhaps we need a newer version, or what version of Java do you have installed?

This error means your java version is lower than the one used to compile this jar.
To run closure you need at least java 7.

I haven’t heard of Google Closure before now, but am happy to try it! (am somewhat confused as to why i can compile with “-final -minify -yui” without needing to updata java, but see this error when i remove the “-minify -yui” and just use “-final” )!

as for java … i only have the Java jdk1.6.0_45 installed (after uninstalling everything when Java broke a few months ago. Java -- Which version/s to use? (June 2015)).

Which one of these would i need ?
http://www.oracle.com/technetwork/java/javase/downloads/jre7-downloads-1880261.html
or is it one of these that i’d need ?
http://www.oracle.com/technetwork/pt/java/javase/downloads/jdk7-downloads-1880260.html

My windows is 64 bit, but what would i need to compile this jar ? the x86 or x64 version? and is installing it likely break compiling to android again as it has done in the past ?

When you add the -yui flag you switch from closure to yui, so you don’t get error in that case.

If you don’t need to compile java application the jre is enough, otherwise take the jdk (which contains a jre copy).

You don’t need to recompile the jar, you just need a java version at least as high as the one used to compile it, here 1.7.

If you have a 64bits windows you should probably take the x64 version.

Compiling to android does use java so it can affect it, but it shouldn’t be a problem here, the android target is compatible with java 7.

Have installed jre-7u79-windows-x64.exe ,

have amended the JAVA_HOME variable to be C:\Program Files\Java\jre7\
have amended the path to now include C:\Program Files\Java\jre7\bin

and i still receive the same error as before if i attempt to build using -final.

I’ve only ever used the older version of the Jave JDK as i read “We recommend that you only use the Java 6 JDK for Android development.” here -> http://www.openfl.org/documentation/setup/platforms/setup-android/

Have installed jre-8u65-windows-x64.exe and changed both the JAVA_HOME variable and updated the PATH also (the installation recomented the removal of the vulnerable jre-7u79-windows-x64.exe installation which i agreed to).

I still receive the same error message as before when i attempt to build using -final , with a working .js output file still at 537KB

java - version has been showing the correct (and recently installed) version

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

and i’ve tweeked the path to ensure the first entry in both use PATH and system PATH are both

C:\Program Files\Java\jre1.8.0_65\bin

yet still this error persisted whenever i tried to use -final

I’ve just found the -verbose option and added it to the command line to get a better idea of what was going on i.e.

openfl build html5 -Dperformancetest -final -verbose

and found my problem is down to the following line

Reading HXCPP config: C:\Users\me\.hxcpp_config.xml

examining that file i find it has the following line.

<set name="JAVA_HOME" value="C:\Program Files\Java\jdk1.6.0_45" />

which i can only assume is temporarily amending the JAVA_HOME variable which is to be used during this build, to the older JDK, rather them my desired newer JRE.

amending that line in the .hxcpp_config.xml file to:

<set name="JAVA_HOME" value="C:\Program Files\Java\jre1.8.0_65" />  

finally lets me compile with the -final flag (but breaks building to android completely, as it can no longer find jdk1.6.0_45 . )

I can only assume from this that i would need to have at least JDK 1.7 with the JRE 1.7 included within it, to be able to compile to android, and to use -final or -minify on code also ? (so going back to an earlier post, which version SHOULD i be using with openfl, or do i need to keep editing paths, vars and the .hxcpp_config.xml file depending on what i’m doing ? )

So I finally have a result to share compiling a single trace(“Hello World”); with -final , and it’s pretty huge still, coming in at 273KB (with 10 warnings which i can only assume are from Google Closure ? )

Wait, you installed JRE 1.8.0_65, but not that version of the JDK? The JRE is only good for running Java, not building it.

I’ve replaced that now with the JDK 1.7, as no-one has suggested JDK 1.8 would work correctly.

and yes, i know that in order to build java (i.e. for android), i’d need the JDK. but as mentioned above, i was trying to build html5, which doesn’t need the JDK, but does need a minimum of JRE 1.7 to allow Google Closure to run when i used -final when building.

The above does mean, I can’t continue to use JDK 1.6, and compile with -final, unless i briefly edit the .hxcpp_config.xml file to set the JAVA_HOME to JRE/JDK 1.7 !

However now that everything appears to do what it’s supposed to do, I’m still seeing 273000 bytes of .js file which i was expecting to have been reduced to much closer to zero. Somethings doesn’t seem to be working as i would expect with dead code elimination, and i’m not sure where to look next to resolve it.

Dead code optimization only remove unused code, there’s a lot happening behind the scene and a lot of classes used internally.

And 273Kb isn’t that much, by how much does gziping it reduce the size?

Instead of editing it back and forth, try conditionals:

<set name="JAVA_HOME" value="C:\Program Files\Java\jdk1.6.0_45" unless="html5" />
<set name="JAVA_HOME" value="C:\Program Files\Java\jre1.8.0_65" if="html5" />

I’d disagree, 273Kb is considerably more than i’d expect to see if unused code is removed! - I expected a small overhead, but i’m looking for a way to remove as much unused code as possible, rather than only around half of it !. if i quickly scan the resulting .js file i see swathes of code which would never be used, which would still be there if it were gzipped ! (which comes in at 65KB if i use 7Zip to turn just the .js into a .gzip file - which, whilst i’m unsure how to use the .js.gzip file in this state, is also triple the size of the mention bunnymark test, which i assume included graphics and alot more code that a single Trace(“Hello World”);.

Maybe i should phrase what i see as the problem in another way, i’ll try with an example

Why does my .js output file contain a reference to, (for example), “SoundTransform”, when it’s not needed in my project ?
Why has it been included during my build, when i haven’t imported it into my project with “import openfl.media.SoundTransform;” ?
Why isn’t the dead-code-elimination process realising it isn’t needed, and isn’t ever going to be called, and failing to remove it ?

With just:

class Main extends openfl.display.Sprite {
    public function new () {
            super();
    }
}

I’ve got 1.2Mo in normal mode and 207Ko with final.
Using dce I’ve got 422Ko in normal mode and 207Ko with final.
So that seems to be the weight of openfl.

I don’t have SoundTransform but I can see KeyboardEvent, but that’s something dce cannot remove since you may not use it but openfl still deals with it for you. It’s not something you can just use if you want, it has to be plugged in the core code. So it’s always used and dce ignores it.

The gzip was just to see by how much the web server could compress it if the client’s web browser support gzip.

It’s possible to gain size if you’ve got multiple games but extracting openfl into its own js file, it’s not easy yet (you can see some steps here Loading components) but hopefully one day it’ll be added as a possibility.

I still dont understand why Dead Code Elimination doesn’t remove it? does it not try to ? or can it not tell it’s dead code?

Taking your example of “KeyboardEvent” , as I know my trace(“Hello World”); example doesn’t ever require or call keyboard events, I know in my mind that it’s dead code, so i have manually eliminated every function relating to “KeyboardEvent”, “onkeydown” and “onkeyup” from the resulting .js file. My project runs perfectly without errors, and i’ve reduced the .js file size down from 1371KB to 1356KB , saving 15KB (before minification)

my project also doesn’t use a Joystick (i spotted code along the way) so i’ve just removed that from my .js file too - bam , that cuts another 11KB - I’m down to 1345KB already. thats a 2% saving on filesize in just a few minutes.

I could go on for a while manually reducing the size further, but i’m really hoping there is a way to automate this code reduction process, or better still not add the unneeded code at build time ?

Dce cannot remove it because this code is used, just not by you but by openfl, it’s not dead code.

Openfl always process keyboard (for example) events,
if it didn’t have a reference to it then yeah sure dce could remove it,
but then when you want to use it it wouldn’t work since openfl wouldn’t translate the web browser (sdl for other targets) keyboard event to flash-like openfl events since it wouldn’t use it.

The code of openfl can’t know if you use a feature or not and only include it in the main event loop accordingly.

I am trying to reduce JS size, and I am experiencing weird behaviours:

-minify reduces size from ~4.1MB to ~2.5MB
-minify -yui reduces size from ~4.1MB to ~3.6MB
-final reduces size from ~4.1MB to ~1.6MB, but when running the application I have a strange behaviour, it looks like there are some errors and the app crashes (NaN instead of Int, something is going wrong)

  • dce recreates the same problems as -final: I think -final is just a shortcut for -minify + dce, right?

So I think the problem is dce, maybe it does something more than requested, but how do I find where the problem is? Currently -minify is the only viable option for me.

Speaking like a Penry (just kidding :wink:) I think that passing from 4.1MB to 1.6MB (if -final worked for me) is great, but… I think 1.6MB is still AWESOMELY BIG for an application like this one, and if I mentally remove the openfl 207kb I still have a huge JS! Why?
Does it include the -whole- libraries I am using (actuate, spritesheet, thx…)?

What are errors you got?

Maybe because some of classes/functions you actually use got removed by DCE.
Consider using keep macro to prevent them from getting removed.