Our app has several JS library dependencies which are already minified. We're considering concatenating them into a single file to reduce the volume of separate threads the browser needs to download them all.
The minifiers I've looked at so far don't handle this well (examined Google Closure Compiler, YUI Compressor). I don't really need my already minified libraries minified again. What is the standard practice for this in the JS world? And do I need to worry about specifying order?
Question is similar for CSS. These libraries provide pre-minified CSS, which I'd like to concatenate together.
You typically wouldn't minify code that is already minified. If the provided minified library was minified in a bad way (like packer), it would be better to minify the original library source code using your favorite minifier.
In your case it's better to look at concatenation only.
You can do this using Gulp or Grunt. Both are able to generate sourcemaps.
I have not had any trouble with use strict when concatenating multiple libraries to a single file, but it is something to pay attention to. Properly written libraries apply use strict only to their library scope, to not affect the global scope / other libraries.
If some silly library applies use strict to the global scope, and another silly library is not compatible with strict, Firefox (probably Chrome as well) throw a strict violation error immediately, so this error is easy to spot.
Related
I've recently created a JavaScript library using Google's Closure Compiler: https://github.com/bvaughn/task-runner
I intend for this library to be used by applications that also require the full Closure Library, and so I want the built version of my library (Task Runner) not to include a subset of Closure Library. If Task Runner includes a subset of Closure Library, and another application includes the full Closure Library, a race condition will exist between which loads Closure last (last in wins). It also bloats the size of the Task Runner file.
However I'm having trouble. If I don't require any of the Closure library classes, Task Runner builds fine (obviously). However if I require something (goog.dom for instance) then my "compiled" JavaScript file also includes a portion of the Closure library. Is there a way to tell the Closure Compiler to leave certain JavaScript files/modules/whatever out of the built result?
FWIW, the Plovr experimental-exclude-closure-library option seems to somewhat describe the functionality I'm looking for.
On the surface what you are asking makes no sense. You want to depend on/use code from Closure-library, but not include it in your output. This isn't really possible nor how the library and compiler function together.
There is a rather small list of primitive functions defined in Closure-library that are completely removed/replaced when compiled with Closure-compiler. goog.require and goog.provide are the two most prominent of those.
For the vast majority of the Closure-Library, if you use or depend on a class, method or object that specific code will appear in the compiled output. And because that library code itself may depend on other parts of the library, even more code may be included in the compiled result.
The difference between using Closure-compiler with Closure-library as compared to more traditional JavaScript libraries is that ONLY the parts of the code determined to be called and used are included in the output. This is much more granular than a simple file inclusion - prototypes, variables, constants, etc will all be excluded because the compiler can determine that they are never used.
Distributing a Library
If you are building a library which depends on Closure-library, you have two options.
Distribute a compiled/built version
You would compile your library using Closure-library; exporting any public API methods and properties. Others who utilize your library with Closure-compiler or Closure-library will need to use an externs file and include your library AFTER compilation.
Distribute your library as source
You would simply distribute your library source code. Others would goog.require your library as part of their source and build process. If Closure-library is used in both projects, it will only be included once in the build process.
There is no hybrid approach where you compile your code but exclude Closure-library. This violates the principle that all of the source code will be compiled simultaneously.
You can peruse my Geolocation-marker library to see an example. I provide a compiled standalone version of the code for use, but the uncompiled source can also be included in other projects which use Closure-library.
I'm trying to make use of a Haxe library in Javascript. Since I already have a project written in Javascript, porting that to Haxe + using the given Haxe library isn't really a solution I'm ready to take at the moment.
Is there a way I can just compile the library from it's Haxe source folder to a JS file that I can then include in my <script> tags and refer to in my project? If I'm not mistaking, when a Haxe project normally compiles, it only includes the classes actually used in your project (correct?) - therefore I need some kind of tool or compiler options that will include all the classes in a given directory.
I would assume packages will get namespaced into Javascript objects at that point.
In case this helps, the library I'm looking to transcompile is Nape (Physics engine written in Haxe).
Looks like I found a way!
From FlashDevelop, create a new Haxe project (for JS).
Then, add a reference to the library that you wish to compile, either by:
Finding it in your Haxe install directory/haxe/lib/name_of_library/version_of_library.
Or, simply by adding the library name in your project settings, under Libraries (as shown in the picture below).
Third (most important step), add --macro include('your_library_root_packagename') in the Additional Compiler Options (replace with your library's top-level package name, obviously!)
I believe that if you have a library consisting of many top-level packages, you would need to enumerate several of those --macro compiler options. In my case I just needed the one.
Finally, CTRL+ENTER... wait for it to transcompile and Voila!
You have a Library in Javascript format!
For some javascript packages I can only get the minified/uglified file. I need to combine them with my other javascript files and compile with google closure compiler.
My question is:
Is it preferable to pass the raw unminified javascript to closure compiler, instead of the uglified one? (in particular with the advanced optimization mode.)
Since many javascript library provide minified version itself(like jquery and angularjs), do I need to worry if I included those scripts in another minification task(uglify or closure compile). Or should I single them out and only concatenate them?
If micro-optimisation is your thing, you might want to have a look at several minifiers to see which is the best fit for your codebase. The main ones are UglifyJS, Google Closure Compiler and ESMangle. There's a nice comparison on the Uglify website. Running code through several minifiers may seem like overkill but if it yields better results then why not. :-)
Minifiers don't care if you pass in something thats already been minified; as an example I use the r.js optimiser in production, and that concatenates my unminified source code and minified jQuery and the like, then uglifies the whole lot.
You don't need to really worry about reminifying libraries, all it's going to do is add more time onto the build step, so if it's taking too long then you could split out the libraries from the minifier and simply concatenate them.
There are two paths depending on the library:
If the library provides the unminified source AND it is known to be compatible with ADVANCED_OPTIMIZATIONS then the best option is to pass it in as a source file. This option reaps the benefit of dead code elimination on the library source as well as your source.
If the library only provides the minified source OR is known not to be compatible with ADVANCED_OPTIMIZATIONS, then the best option would be to compile your code using externs for the library. For minimizing the number of requests, you should still concatenate the results together. While you could use the WHITESPACE_ONLY level of the compiler, it may not be the best tool for that.
Of course combining a library with your source will minimize requests, but will at the same time nullify any caching benefit from using a CDN for the library hosting.
I have some javascript files that I want to live independently of each other. Each of these files reference other files for some library functionality.
Finally, there are times when all of this code can be used at the same time. I know that referencing a javascript file is not equivalent to a c++ include or java import. Is there a way to achieve that kind of behavior?
For performance reasons you probably should concatenate them all into one. Compress that one using Google Closure and then serve it as a single and cacheable file.
I don't know about any native interface specification in Javascript. You "only" need to make sure the things you reference/access are already loaded. This may become messy if there are lots of dependencies.
That's why big JS-frameworks have some code for module loading and dependency specification.
Libraries I would name here are head.js and RequireJS.
But think what size of tool you really need.
I keep getting errors that the function (renamed) does not exist for the given object. Is there a release or setting or something to make it work?
You must use an externs file for jQuery when using Closure Compiler Advanced Mode with jQuery. Extern file will tell compiler these are reserved methods and accept these argument and argument data types should be like that, so do not minify method names and check argument data types in that way.
You can get externs file which is created by Google Developers here. This file generated for jQuery-1.4.3. But currently probably will work any version of jQuery. Newly added methods may not include in that file, so you should add it to externs file, syntax and synonyms are so simple.
Also you can say location of externs file to compiler by using an extra compier flag. Syntax should be like this
--compiler_flags= "--externs=path/to/jquery.externs.js"
Also you can use this tool which is an online externs extractor for Closure Library.
You have to declare jQuery as an extern to the compiler...however I'm not sure if anyone's made one, there was an extern file for 1.3.2, but I haven't seen any 1.4+ versions.
Edit: this issue thread here has the community building a 1.4 version.
jQuery is not compatible (yet) with the Closure Compiler in advanced mode. I agree it would be a very good thing to make it compatible, because its method-chaining syntax lends very readily to prototype virtualization for much improved execution speed.
In fact, among the popular JavaScript libraries (other than Closure Library, that is), only the Dojo Toolkit is compatible with Closure Advanced mode.
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t