Three.js: Google Closure Compiler "externs" file for three.js ?

Created on 10 Jul 2011  ·  61Comments  ·  Source: mrdoob/three.js

Hi

Is there any externs file for three.js ? I mean such one:

http://code.google.com/closure/compiler/docs/api-tutorial3.html#externs

Thanks
Remo

Question

Most helpful comment

Hmmm, I'm still not super happy with having tons of comments in the code. Sometimes I wonder if it wouldn't be better to port the whole thing to something like TypeScript instead (too bad that one is owned by Microsoft).

All 61 comments

No, three.js doesn't have any external dependencies, so something like this wasn't needed so far.

I know, but it is also useful for own projects to integrate THREE.js in a compilable environment.

How would such file look like? Sorry if it's explained already on the link you shared, I found the page a bit overwhelming (too much text) and I'm unable to read/understand.

@mrdoob, you find some of their examples at:

http://code.google.com/p/closure-compiler/source/browse/#svn%2Ftrunk%2Fexterns

or

http://code.google.com/p/closure-compiler/source/browse/#svn%2Ftrunk%2Fcontrib%2Fexterns

and the following is also important:

http://code.google.com/closure/compiler/docs/js-for-compiler.html

Comments/Headers? I think that would make the code harder to read...

Yeah, but i think it is only for this extern file not for the whole code. One can do it, but it is not necessary.

I've tried it with http://www.dotnetwise.com/Code/Externs/index.html . But it doesn't work completely with Three.js . Not all definitions are extracted.

Here is the blog entry:

http://blog.dotnetwise.com/2009/11/closure-compiler-externs-extractor.html

Seems like it supports the this.method = function(){} pattern, but not the prototypes...

@mrdoob, what is your recommendation to integrate THREE.js in a own application with closure-compiler advanced optimizer ? Is it true that is currently not possible ?

As far as I understand advanced optimizer only includes the classes being used, right? In theory it should work... is it not working?

I didn't try advanced optimization with three.js, but I remember for other things it used to break the code. In general it wasn't "safe" - with default simple optimization it always works, with advanced sometimes it doesn't.

It breaks the code if you compile is as a library, but as a application (with methods being called and all that) it should work, right?

@mrdoob to use a library with compiled (optimized) code you need a "externs"-file to declare all of the classes and methods of the library. It doesn't work without it. But is there another tool that works with three.js ? I need it to obfuscate (uglify) my three.js-application. One candidate is: https://github.com/mishoo/UglifyJS . But i don't have tried it.

Google closure externs is a file, that describe whole objects, that we will use in our compiled code.
Without this file compiler just makes from function names something like a() or b().

For example, this is for JQuery: http://code.google.com/p/closure-compiler/source/browse/trunk/contrib/externs/jquery-1.7.js

It'll be great if externs wiil be for three.js.

I'm cool with that, but I can't tackle it myself. Someone else will need to step up on this one.

@yurikor, when you use node.js, you can use node-browserify and uglify-js together. Then you don't need to build anything.

@remoe Thanks a lot for advice. I'll try it.

This issue has been inactive for a while, but in case anyone wants to tackle this problem in the future, here's some additional information:

For my project, I have created a simple file with just enough threejs exports to be able to compile my project. It comes with type annotations which was quite useful as it enabled the closure compiler to check all types and find a couple of bugs in my code. I have created this file manually. I use the closure compiler mainly for bug checking, for the actual minification I use the less powerful but safe uglifyjs.

Also, to prevent the closure compiler from renaming my public interface symbols, I had to add several lines of code (those four functions are the only public functions of my library). Note that the closure compiler renames all properties accessed via blah.xyz, but does not touch any properties accessed via blah["xyz"].

Finally, the line window['ColladaLoader2'] = ColladaLoader2 (note again the use of a string) was needed to tell the closure compiler that this class should be exported to the global scope.

But you aren't using closure for production, and just bug checking? I am
unsure if maintaining the extern file is worth it then. Just run closure
without aggressive optimizations and then you don't need the extern file
but you still get most of the validation I believe or maybe all of the
validation. Maybe you can clarify?

Sent from my phone, sorry for my grammar and terseness.
On Feb 12, 2013 5:19 AM, "Robert Carnecky" [email protected] wrote:

This issue has been inactive for a while, but in case anyone wants to
tackle this problem in the future, here's some additional information:

For my project, I have created a simple filehttps://github.com/crobi/ColladaAnimationCompress/blob/master/threejs-exports.jswith just enough threejs exports to be able to compile my project. It comes
with type annotations which was quite useful as it enabled the closure
compiler to check all types and find a couple of bugs in my code. I have
created this file manually. I use the closure compiler mainly for bug
checking, for the actual minification I use the less powerful but safe
uglifyjs https://github.com/mishoo/UglifyJS.

Also, to prevent the closure compiler from renaming my public interface
symbols, I had to add several lines of codehttps://github.com/crobi/ColladaAnimationCompress/blob/366344d3aa5dbbc0a53c47a2c1759b86bb1e0fcd/ColladaLoader2.coffee#L3376(those four functions are the only public functions of my library). Note
that the closure compiler renames all properties accessed via blah.xyz,
but does not touch any properties accessed via blah["xyz"].

Finally, the linehttps://github.com/crobi/ColladaAnimationCompress/blob/366344d3aa5dbbc0a53c47a2c1759b86bb1e0fcd/ColladaLoader2.coffee#L3383 window['ColladaLoader2']
= ColladaLoader2 (note again the use of a string) was needed to tell the
closure compiler that this class should be exported to the global scope.


Reply to this email directly or view it on GitHubhttps://github.com/mrdoob/three.js/issues/341#issuecomment-13426131.

As far as I know, the simple mode does not do any validation at all. It renames local variables, and if it encounters an unknown symbol, it leaves it untouched, assuming it's a global variable.

The advanced mode behaves like a compiler in a strongly typed language (assuming type info is available): it warns about unknown functions or properties, warns if you called a function with the wrong number of arguments or if you have used a string parameter where a number was expected.

As an example, the simple mode transforms the following code

function fn() {
    var foo = {}; // local variable, safe to rename this
    foo.bar();    // undefined property, will crash here
}
fn();

without any warnings into

function fn(){({}).bar()}fn();

which will obviously crash on ({}).bar(). The advanced mode outputs the following code

({}).a(); // fn() inlined, private member 'bar' renamed to 'a'

which still crashes, but the compiler also gives a warning

Property bar never defined on foo at line 3 character 0.
  • The bugs closure found were the type of bugs where I had a typo in a function name or where I passed one THREE.Vector3 to Matrix4.makeTranslation instead of three separate numbers for the x, y, and z components.
  • If I had full test coverage (which I don't), I would have found those bugs sooner or later. Sometimes they are hard to debug, though, if they don't manifest immediately.
  • If threejs supplied an up-to-date exports file with each new release (huge effort to maintain), the closure compiler would catch all problems coming from a changing API (as was the case for Matrix4.makeTranslation).
  • Setting up the closure compiler is too much work for me, as it needs a java runtime. All other tools needed to build my library are based on node/javascript.

I'm currently building my closure library externs.js file in order to integrate a THREE.js application with Closure Library. Basically what we are trying to find out is:
Is there a list somewhere of all the THREE.js classes and the prototype methods they implement? The list should be something like this:

THREE.Texture
THREE.Texture.constructor
THREE.Texture.clone
THREE.Texture.dispose
THREE.DataTexture.clone

(and so on...)

Ps- Three.js is great, but with proper jsDocs, this list could be easily extracted :)

I have a partial implementation of three.js exports here (written manually, so might contain some errors).

@crobi: why did you put the doc comments into it? That seems like it was rather time consuming and I'm not sure it's necessary...

@taoeffect: the comments are mostly for the closure compiler advanced mode. I like strongly typed code.

@crobi, oh the comments result in enforced typing? That's kinda cool, I didn't know it did that.

Only if you use the closure compiler to check for type errors. Similar to typescript. Both preprocess annotated javascript into plain javascript. So it's a compile-time check only.

Most of the comments about closure's advanced optimizations mode here are inaccurate.

To address the main issue, you can use the following tool to automatically generate closure externs for any library http://www.dotnetwise.com/Code/Externs/

Also, if you decide to use three.js as input to your code instead of simply using it as an external library, you'll need to add the flag

--language_in=ECMASCRIPT5

You should write a blog post about this, maybe taking a performance
critical example and seeing if running it thorugh the Google Closure
compiler with good optimizations makes a difference.
-ben

On Mon, Jan 13, 2014 at 12:31 PM, Rodrigo Formigone <
[email protected]> wrote:

Also, if you decide to use three.js as input to your code instead of
simply using it as an external library, you'll need to add the flag

--language_in=ECMASCRIPT5


Reply to this email directly or view it on GitHubhttps://github.com/mrdoob/three.js/issues/341#issuecomment-32191167
.

Best regards,
Ben Houston
Voice: 613-762-4113 Skype: ben.exocortex Twitter: @exocortexcom
http://Clara.io - Professional-Grade WebGL-based 3D Content Creation

I guess I just might write such a post. Just to clarify, though, the reason one would want to run Three.js through closure (with or without an externs file) is not necessarily only for the performance optimizations. Closure is primarily intended to help you write maintainable code in JavaScript (particularly, very large code bases). The goal is to help developers "tame" JavaScript (writing native JS), rather than to "avoid" it (using GWT or other similar tools). If you simply try to compile Three.js as part of a Closure project, the compiler might yell at you because Three.js might not conform to some of its standards (not JSDoc'd enough, maybe?). Using the --language_in compiler flag solves that as of right now, though you'll get a few warnings. If you simply want to compile your own JS code, but reference Three.js as an external library (thus leaving all of Three.js's codebase untouched and unoptimized), you will need the externs file mentioned above. Without the externs file, Closure will throw compilation errors saying that THREE.* is not declared anywhere, etc.

While I don't get to writing my blog post explaining how and why one might want to use Three.js on a Closure project, here's the best introductory presentation on Google Closure tools I've seen: (From Google I/O 2011) https://www.youtube.com/watch?v=M3uWx-fhjUc (I know it's a long video, but really makes it clear what the purpose of the compiler is, and what the different compilation modes actually do. It also describes why you'd need an externs file).

Hi, I'm looking forward to developing an application using three.js, and so desiring ADVANCED_OPTIMIZATIONS option support.

Dead code removal strongly works when the embedding application uses only a part of Three.js functions.

Currently, three.js requires every single function developed, because the intended usage is confined to "Just require three.min.js!".This classical approach is easy to understand, but for codes written by this approch, JavaScript minimizers can reduce code size only by shrinking variable names (not effective for short variable names), removing spaces (only effective for indent spaces, tabs and line breaks) and other cheap tricks.

By using ADVANCED_OPTIMIZATIONS option to a "Closure compiler styled" code, it can remove the entire "not needed codes", which mostly weights large libraries. Libraries like Closure library had become large, but library users and developers don't care about it because they know that most of the code will be removed on compiling stage.

Since three.js is already written in object-oriented style, I think it's not (technically) difficult to update the entire code to "Closure compiler styled" code. The things I worry about...

  • Closure compiler style requires annotations for each function. Currenly, there are none of them. How long will it take to add annotations to all functions ever developed?
  • Closure compiler requires strict type definitions. Even for null and undefined, you should work for them properly. It might be a hard work for functions that have "null-allowed" parameters, "undefined-allowed" parameters, ...
  • You should prepare a proper externs file, if you're looking forward to preparing the "full-versioned library" compiled by ADVANCED_OPTIMIZATIONS.

Hai Schedul Xor,

This is a nice idea to go about. Could you share a small snippet, on how
this has to be added to three.js?

With regards,

Ramsundhar Madhavan

On Tue, Jun 24, 2014 at 4:23 PM, Schedul Xor [email protected]
wrote:

Hi, I'm looking forward to developing an application using three.js, and
so desiring ADVANCED_OPTIMIZATIONS option support.

Dead code removal strongly works when the embedding application uses only
a part of Three.js functions.

Currently, three.js requires every single function developed, because the
intended usage is confined to "Just require three.min.js!".This classical
approach is easy to understand, but for codes written by this approch,
JavaScript minimizers can reduce code size only by shrinking variable names
(not effective for short variable names), removing spaces (only effective
for indent spaces, tabs and line breaks) and other cheap tricks.

By using ADVANCED_OPTIMIZATIONS option to a "Closure compiler styled"
code, it can remove the entire "not needed codes", which mostly weights
large libraries. Libraries like Closure library
https://developers.google.com/closure/library/ had become large, but
library users and developers don't care about it because they know that
most of the code will be removed on compiling stage.

Since three.js is already written in object-oriented style, I think it's
not (technically) difficult to update the entire code to "Closure compiler
styled" code. The things I worry about...

  • Closure compiler style requires annotations for each function.
    Currenly, there are none of them. How long will it take to add annotations
    to all functions ever developed?
  • Closure compiler requires strict type definitions. Even for null and
    undefined, you should work for them properly. It might be a hard work for
    functions that have "null-allowed" parameters, "undefined-allowed"
    parameters, ...
  • You should prepare a proper externs file, if you're looking forward
    to preparing the "full-versioned library" compiled by
    ADVANCED_OPTIMIZATIONS.


Reply to this email directly or view it on GitHub
https://github.com/mrdoob/three.js/issues/341#issuecomment-46957189.

@schedul-xor we definitely need help with that... are the code anontations really required or is it enough with externs?

Hi,

I am new to this community, I would be interested in contributing these
changes.

With regards,

Ramsundhar Madhavan

On Tue, Jun 24, 2014 at 7:23 PM, Mr.doob [email protected] wrote:

@schedul-xor https://github.com/schedul-xor we definitely need help
with that... are the code anontations really required or is it enough with
externs?


Reply to this email directly or view it on GitHub
https://github.com/mrdoob/three.js/issues/341#issuecomment-46973166.

Keep in mind that advanced optimizations require a certain coding style or they will break your code. For example, three.js mixes uniforms["diffuse"] and uniforms.diffuse, which is not allowed under closure advanced optimizations. See also #3222.

Adding strict type annotations everywhere is a huge amount of work, and adds lots of comment lines (in my project, it increased the line count by a factor of 2).

Having externs files for other web frameworks/languages is nice.

According to the tutorial, externs are used to protect variables you don't want to be renamed. This is what you use when you want to protect (non-closure compiler styled) third-party libraries, using in your closure compiler styled project, from aggressive variable renamings.

I'm not sure if the compiler will still try to cut dead code even when the externs file is the only thing provided. It'll be much more easier if you should only write externs file, rather than writing annotations to all functions...

Even though, in my opinion, writing annotations to each function is better than writing externs, because it will become hard to sync externs file afterward, if type definition file and source code is different. You may imagine how annoying it will be if each function fix requires externs file update. Either choice (externs or /** */ comment on functions) requires annotation, in most cases easier method wins.

Since three.js is a large project, I am wondering where I should first work on. It'll be better to start from what it can be easily done.

How about putting file headers, change function definition style for each function?

THREE.Material = function(){
  :
};
THREE.Material.prototype = {
    constructor: THREE.Material,
    setValues: function ( values1, value2 ) {}
    getValues: function () { return this.a; }
    :
};

goog.provide('THREE.Material'); ← Write goog.provide('package.classname') at the first line

← three empty lines before @constructor

/**
 * @constructor ← Add @constructor annotation to constructor
 */
THREE.Material = function(){
  :
};

← two empty lines before function definition
/**
 * @param {!Array.<!string>} values1 Values1 explanation ← values1 is an array of strings. values1 can't be null, and elements inside values1 can't be null.
 * @param {!number} value2 Value2 explanation ← value2 is a number.
 */
THREE.Material.prototype.setValue = function(values1, value2){
  goog.asserts.assertArray(values1);
  goog.asserts.assertNumber(value2);
  :
};


/**
 * @return {!number} ← This function returns a non-null number.
 */
THREE.Material.prototype.getValue = function(){
  return this.a;
};

It will be easier to strict all parameter types and returning value types to non-null. This will make it much more easier to pass ADVANCED_OPTIMIZATIONS compilation errors.

Hmmm, I'm still not super happy with having tons of comments in the code. Sometimes I wonder if it wouldn't be better to port the whole thing to something like TypeScript instead (too bad that one is owned by Microsoft).

Typescript feels much nicer for strongly typed javascript than closure. This is my experience after having rewritten a moderately sized collada loader first to closure-compliant javascript and then to typescript. Both approaches helped finding bugs at compile time. Closure performed some quite nice optimizations (inlining, dead code removal) of my code, and has support for nullable types. On the other hand, the huge amount of comments was distracting and the IDE support (for code completion) was not as good as with typescript. Plus, writing classes in typescript is much easier due to the ECMAScript6-like class keyword.

But that is just a personal opinion. More importantly, I want to stress again the fact that you must make sure all property accesses are consistent before officially supporting closure in advanced compilation mode. Having an externs file does not help, the property access has to be consistent for internal objects which are not exported, since you _want_ those to be agressively renamed/inlined/removed. You will catch inconsistent property accesses if you annotate every class and every variable, but doing this for the entire three.js codebase is several weeks of time (if I extrapolate how long it took me to annotate my project).

Finally, porting such a big project as three.js to any other language/framework/coding style is something that should be discussed in detail.

OK, I agree that three.js is enourmous, and so adding annotations to each functions may take several weeks. There might exist better AltJSs than closure. This must be discussed (if you're looking forward to porting it to something else) more deeply.

Sorry, I can't wait. I'll fork the current commit and start porting.

Hi,

Is it possible to automate adding this annotations?If so, we can added it
to build.py and add just before we enable advanced optimization of closure.

With regards,

Ramsundhar Madhavan

On Wed, Jun 25, 2014 at 6:05 AM, Schedul Xor [email protected]
wrote:

OK, I agree that three.js is enourmous, and so adding annotations to each
functions may take several weeks. There might exist better AltJSs than
closure. This must be discussed (if you're looking forward to porting it to
something else) more deeply.

Sorry, I can't wait. I'll fork the current commit and start porting.


Reply to this email directly or view it on GitHub
https://github.com/mrdoob/three.js/issues/341#issuecomment-47047966.

@ramsundhar20 , in my opinion, adding annotations (inaccurate? better than nothing. not a big problem. it can be updated) first will make automation much more easier.

Three.js currently contains 163 javascript files with 1354 functions defined. Yes it's huge, but it's not a goal that's too far.

// I'm scared if this topic is out of place ...

@schedul-xor again, I'm not really a fan of having a comment per function :/

@mrdoob OK, I understood.

Respecting your policy, I would like to add comments per function only in my fork. Also, I'll never make any pull requests. Instead, I'll port the original three.js modifications to my closure-styled fork. Your favorable consideration would be appreciated.

That sounds good :)

Thank you! I'll start working on it.

Is there at least a base three.js externs file to be used with closure compiler? That does not require Three.js source code to have any additional google style annotations, this is just to make the linking from an external app.js that uses three.js compilable/obfuscated enough?

I'm also very interested in a quality, complete externs file for three.js. Here's one, but it's not complete:

https://github.com/cljsjs/packages/blob/master/three/resources/cljsjs/three/common/three.ext.js

I suppose one way to go is to start with this one, and manually add stuff you use.

Yes, count my vote. Ideally for an advanced mode compilable, 100% typed threejs - or an externs file at the very least.

Type inference has gotten better and the required clutter got less. With scopes and aliases in place, the code does not have to read as verbose as the closure library. It pretty much comes down to writing typed inline docs in case of clean code. Are those really bad enough to outweigh all the benefits?

Super-aggressive settings, that is advanced mode + JS compression + type-based optimizations, will not only remove dead code but can do all the cool stuff an optimizing compiler can do:

Named constants / enums will be replaced with numerals. Also, the compiler can trace constness, perform computations with other constants and finally insert a plain number where it's needed. Dependent flow control gets subjected to dead code elimination, of course. Functions that only have one active call site in the resulting application and ones whose compressed form will end up smaller than their definition would save get inlined. Namespaces are removed. All unprotected names are shrunk to a minimum.

Lookup is comparatively expensive in JavaScript. The combination of renaming, constant folding and inlining will remove a lot of lookup plus numerous function calls. On top of that, given an approriate header (there is one in the closure library), all the standardized WebGL constants can be baked into the renderer.

The result is a smaller, faster, self-documenting and automatically customizable library. The compiler will also catch a lot more bugs under more aggressive settings - it will probably ease code review. Last but not least, there is the obfuscation effect: Lumping together the client code with the customized library provides a much better protection against theft of intellectual property than code with revealing symbols that were preserved by means of an externs file.

I can't find the branch mentioned above. Is anyone still working on a typed version?

@mrdoob Any hope for a change of heart regarding the mainline?

I'd be happy to help.

@mrdoob Any hope for a change of heart regarding the mainline?

At the moment I'm focusing in refactoring WebGLRenderer 😇

Can change the constants to const rather than var has good support for all WebGL browsers https://kangax.github.io/compat-table/es6/ (const->basic) and js engines are starting to optimise for const Speeding up global constants using fixed field optimization

Interesting, though, as it only works in place of var, only applicable to a very small fraction of the cases I am talking about - even when it would be just about constants. Further, JIT compilers are in a hurry by definition so they naturally can't compete with whole program optimizations performed by an offline tool. Every JS engine must respect the structure of the code and can't refactor it arbitrarily as we expect to be able to e.g. open the console and find the program we put into it, replace a specific function, etc.

Back to closure compiler support: I did some reading and experimentation. Here is what I found out:

  • No annotations are required to run advanced mode,
  • annotations can be added gradually to crank up the optimization level, and
  • the loader needs some care to remain working, but it's fairly easy.

There are basically three different use cases:

  1. The models can be compressed alongside with the application and the library.
  2. The application and the library are compressed. Models are loaded at runtime.
  3. The library is compiled in basic mode and an advanced mode app wants to use it.

The third one requires an externs file for all of Three.js and is a lot of work for too little benefit IMO. So I will only discuss the first two - these are the preferred ones, anyways:

When the compiler sees

anObject['aProperty']

it won't touch the property name (no strings are ever changed).

anObject.aProperty

on the other hand allows the compiler to consistently rename the property, unless it knows that anObject is external to the application being compiled. The compiler knows this from built-in or explicitly provided _externs_.

Here comes the recipe:

  • We make the loader consistently accesses the properties using the dot notation.
  • We type the input and write an externs file only for the JSON.
  • Compiling with that externs file should be all that's needed to get use case 2 working.
  • For use case 1 we do not use the externs file, but instead strip the quotes from the object keys in the JSON:
{
    "camera": {
        "object": {
    // ...

would simply become

{
    camera: {
        object: {
    // ...

Quite simple, isn't it?

Use case 1 becomes even more attractive when the JSON format would allow external binary data (raw or compressed via webgl-loader or o3dgc) - technically another feature completely orthogonal to closure support, of course.

The externs file can also replace ever-outdated Wiki pages documenting the file format :-).

I know this issue has been closed for quite some time. However I recently had the same problem using three.js within a closure compiler project and landed on this page. I wrote a tool which transforms .d.ts (typescript declaration files) to a closure compiler file. Using the tool and the great described DefinitelyTyped/threejs descriptor file it works perfectly.
The tool: https://github.com/eredo/tsd2cce or install via npm install -g tsd2cce

Hope this helps...

@eredo that totally helped me out. All the other generators I tried were missing a good number of method definitions for the three.js library. Thanks!

@eredo @Corkle or anybody else, can you show us how to use tsd2cce? The first arg is clearly the .d.ts definition file, but what is the second arg? I'm getting this issue. https://github.com/eredo/tsd2cce/issues/6

Actually I found that using the r73 d.ts from February does work fine with tsd2cce, r73 is too old for me though.

The proper way to do this now would be to use tsickle to generate from d.ts files.

Hey All,

For posterity and everyone's benefit I decided to report here on my own attempts to shrink the library further with Google Closure Compiler's ADVANCED_OPTIMIZATIONS, and some other tweaks.

I have created an extern.js which allows Three.min.js with advanced optimizations turned on. It is FAR from perfect.

To create it, I started with an extern.js based on earlier examples in this thread. The library was broken when compiled this way because of mangled properties not included in that extern file. Using the --property_renaming_report option on the closure compiler, I got the complete list of mangled properties. After adding ALL of these properties to the extern.js, properties were no longer mangled and the output was the same as SIMPLE_OPTIMIZATIONS. From there I selectively/manually started commenting out sections of the extern.js and confirming that the library still worked in minified form.

I would LOVE to automate this guess-and-check and get a perfect extern.js which safely mangles as many property names as possible. I had the idea of using the unit tests for THREE.JS and programatically determining which mangled propnames resulted in failed tests, but it doesn't seem possible to run the unit tests from command line currently, for example with phantomjs. (Probably due to WebGL) ?

Either way this is "progress" towards a smaller minified library, helping me keep my overall SPA javascript size down.

externs.js

updated package.json build-closure command

I also used string replace commands to remove all console.warn and console.error messages from the library, as you can see in the build-closure command. With this, and commenting out certain sections of code, I've shrunk the minified lib by about 20% so far, and there's room for improvement.

@mrdoob Doing something like my method here, you could eventually supply an extern.js that allows for ADVANCED_OPTIMIZATIONS without cluttering the code with annotations specific to that compiler, which seemed to be your primary concern.

@medmr1 Awesome! Have you tried compiling your app with the three.js library all in one? This would prevent the need for an externs file ideally.

I haven't tried building the whole thing within closure, no. That may work alright but I suspect there will still be issues with respect to mangling some properties referred to programmatically? I.E. stuff like var thing = ShaderLib[ shaderType + "BumpMapFrag"] But perhaps I would save myself a lot of trouble?

Yes, something like var thing = ShaderLib[ shaderType + "BumpMapFrag"] will break with advanced optimizations. property references need to be statically analyzable. You could do something like:

function(shaderType) {
  if (shaderType == "a") {
    return ShaderLib.aBumpMapFrag;
  }
  if (shaderType == "b") {
    return ShaderLib.bBumpMapFrag;
  }
...

Building a correct externs file is definitely more beneficial for the project as a whole as most people will not compile their app with Closure Compiler, only use the published minified version.

Instead of externs, you could also try out the @export annotation.
https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#export-export-sometype

Was this page helpful?
0 / 5 - 0 ratings