Repository: three.js
Issue: Support advanced (property mangling) minify tools
Labels: Suggestion

### Description

Some JavaScript minification tools support reducing the size of code even further by renaming properties. This is called property mangling in UglifyJS, or ADVANCED optimization mode in Closure Compiler. In summary it works like this: suppose you have the following code.

```js
const obj = {
    apples: 1,
    oranges: 2
};
console.log(obj.apples, obj.oranges);
```
Property mangling will rename the object properties consistently, so `apples` is renamed to `a`, `oranges` is renamed to `b`, and so on, producing output that looks like this:

```js
const obj = {
    a: 1,
    b: 2
};
console.log(obj.a, obj.b);
```

This can however break code that is not written to expect this. The main problem is mixing string and dot property syntax. For example if you access a property in `obj` using a runtime string like `obj[someStr]`, then the names are different and the code is broken. To better support this case, both Closure Compiler and UglifyJS support preserving the names of properties that use string syntax. For example code written this way would not have its properties renamed:

```js
const obj = {
    "apples": 1,
    "oranges": 2
};
console.log(obj["apples"], obj["oranges"]);
```

That allows for using property mangling as well as string lookups, providing property accesses consistently use either string syntax or dot syntax, but not a mix, as that means only dot syntax is renamed and then no longer matches the string syntax.

Using data from [Construct](https://www.construct.net/) - a large JavaScript-based game engine - property mangling can further reduce the code size over "simple" (non-property-mangling) minification by ~35-45% uncompressed and ~15-25% compressed. (The range depends on the tool used - Closure Compiler tends to do better than UglifyJS.)

### Solution

Currently three.js mixes dot and string property syntax and so is broken after property mangling minification. After debugging this, one area I identified was the use of `ShaderLib`: in [ShaderLib.js](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib.js) the `ShaderLib` defines properties with unquoted syntax (e.g. `basic`); however in [WebGLPrograms.js](https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLPrograms.js#L93) it does a runtime string lookup with `ShaderLib[ shaderID ]`. It looks like this pattern is used in a few places.

The fix is to ensure all uses of property accesses are consistently string syntax or dot (unquoted) syntax. For example in this case, the fix would be to ensure `ShaderLib` properties use string syntax, e.g. `"basic"`. Other such cases will need to be reviewed across the codebase. I would also suggest to use `Map` for dictionary-style storage like this, as it's a natural fit, avoids some pitfalls with object properties (like `prototype`), and you can only use string syntax, so it actually prevents using dot syntax and so avoids any syntax mix-ups.

Both Closure Compiler and UglifyJS provide a "debug" mode for property mangling to help identify problems. This renames properties but keeps the original name - for example UglifyJS renames `obj.apples` to `obj._$apples$_`, so the property is renamed, but you can still see what it was meant to be when debugging problems.

Once set up it's pretty straightforward to keep things working - it just needs consistency across the codebase with property syntax. It may be a relatively easy change to make, but it should probably be done by someone familiar with the codebase. I don't think it's an onerous requirement to maintain in future, and it helps further reduce the download size and parse/load time as three.js is a pretty large library.

### Alternatives

I think the only alternative is to keep using "simple" (non-property-mangling) minification. This doesn't require any code changes and tends to just work with whatever code you write, so is a bit easier to maintain. However it may turn out to be straightforward to support and maintain support for property mangling, which would make it a relatively easy win.

### Additional context

With Construct we've supported property mangling in our engine for years, and I wouldn't say it's a significant burden.