Script minification

Ashley's avatar
Medal
Construct Team Founder
Published 18 Jan, 2018
417 words
~2-3 mins

Projects exported with "Minify script" enabled will run all script through an advanced minifier. This includes mangling property names to achieve maximum compression, and increase the difficulty of reverse engineering. The process is similar to Google Closure Compiler's ADVANCED_OPTIMISATIONS mode.

JavaScript in addons needs to be specially written to take in to account the minifier if they use external APIs that are not processed by the same minifier. Once you are familiar with what the minifier does, this is a straightforward process. Be sure to test your addon with minification to ensure it won't be broken when users export with minification enabled.

How property mangling works

The minifier will rename dot-property access, but not string-property access. The following code snippet illustrates the difference.

// Before minification:
const obj = {};
obj.dotProperty = 1;
obj["stringProperty"] = 2;
console.log(obj.dotProperty + obj["stringProperty"]);

// After minification:
const obj = {};
obj.a = 1;
obj["stringProperty"] = 2;
console.log(obj.a + obj["stringProperty"]);

In other words, obj.property was shortened to obj.a, but obj["stringProperty"] was left intact.

Usually JavaScript code continues to work normally after this process. However there are two cases to be aware of when writing addons that can end up with code breaking after minification.

Case 1: don't mix dot and string property accesses

The following code snippet mixes dot and string property accesses to refer to the same property. Since only dot syntax is renamed, the resulting code is broken.

// Before minification:
const obj = {};
obj.myProperty = 1;				// dot syntax
console.log(obj["myProperty"]);	// string syntax

// After minification:
const obj = {};
obj.a = 1;
console.log(obj["myProperty"]);	// oops - now undefined

To avoid this problem, make sure you consistently use one syntax to refer to the same property name.

Case 2: external APIs

By default, all property names are mangled, except those on a reserved names list for things like DOM properties. If you load an external API that is not also minified, then property mangling will break the API calls using dot syntax, as illustrated in the following snippet.

// Before minification:
api.myFunctionCall();

// After minification:
api.a();		// oops - not a function

To avoid this, make sure external names use string syntax, since this will not be minified. The difference is shown below.

// Before minification:
api["myFunctionCall"]();

// After minification:
api["myFunctionCall"]();	// still works

You can use this approach with global names as well - simply refer to it as a property on self, e.g. self["MyGlobalApi"].