One question we get asked quite often about developing web applications using HTML5, CSS3, and JavaScript, is about how to conceal code. Reasons range from preventing cheating, protecting intellectual property, hiding encryption algorithms and others. Since JavaScript is executed on the client side, even on Firefox OS, the users can get access the code if they have the skills and spend the time. But don’t get the wrong idea! Applications on Android, iOS and most mobile platforms can be reverse engineered with effort and the right tools.

We will present some measures that make it harder for copycats to reveal your application’s code. In various degrees they will increase the effort, skills and tools required to get the code.

Compressing your code

This is the starting point for most developers. Compressing your code reduces the file size by removing what the browser doesn’t need to run your application. It starts by stripping comments and unnecessary white space. This is a good first step as comments usually reveal a lot of information on how the code is working.

The next level is shortening names of local variables and functions, the so called mangling. As this removes the meaning on those symbols, it further reduces readability.

More advanced compression tools, like UglifyJS, will actually parse your JavaScript to analyze and transform it. This allows not just renaming local symbols but also rewriting conditions and loops into shorter expressions, joining variable declarations (hoisting) and removing unreachable code. The resulting file is not only smaller and less readable but in many cases also faster.

You can take this one step further with the Google Closure optimizer in Advanced mode. The tool allows settings for all the aforementioned transformations. Advanced mode is the most aggressive and requires greater consideration when used, to ensure that the output runs just as the input. It will rename, inline and even remove functions, properties and variables, so you need to make sure to either reference all symbols correctly or annotate them. The extra work pays off as the result is highly compressed and even gains a performance boost. As an example, let’s see what can happen to this code:

document.onload = function() { var shareImage = document.querySelector("#share-image"); function share() { var imgToShare = document.querySelector("#image-to-share"); if (!imgToShare.naturalWidth) { alert("Image failed to load, can't be shared"); return; } // Create dummy canvas var blobCanvas = document.createElement("canvas"); blobCanvas.width = imgToShare.width; blobCanvas.height = imgToShare.height; // Get context and draw image var blobCanvasContext = blobCanvas.getContext("2d"); blobCanvasContext.drawImage(imgToShare, 0, 0); // Export to blob and share through a Web Activitiy blobCanvas.toBlob(function (blob) { var sharingImage = new MozActivity({ name: "share", data: { type: "image/*", number: 1, blobs: [blob] } }); }); }; shareImage.onclick = share; };

Once we’ll run this code through Google Closure, the code will look like: