I have manage to create a small size js application that uses jQuery and jQuery UI using google's closure compiler with advanced optimizations. Just for clarity: I have not compiled jQuery itself, just my app that uses jquery. I would like to know if somebody can confirm that this idea also works for bigger and more complex apps.
The procedure is as follows:
0.- You have an html file that calls jquery-1.4.3.min.js, test1.js, and test2.js
1.- compile your app and export a property map file
java -jar closure-compiler.jar \
--compilation_level ADVANCED_OPTIMIZATIONS \
--js test1.js --js test2.js \
--property_map_output_file prop.out > min.js
The property map is a key/value file that contains the name of the property before and after compilation:
aprop:a
html:b
each:c
2.- Copy prop.out to prop.in and edit it so that jQuery properties (functions) are replaced by the same name (this could be easily automated with a list jquery's function):
aprop:a
html:html
each:each
3.- Recompile using prop in as property map input
java -jar closure-compiler.jar \
--compilation_level ADVANCED_OPTIMIZATIONS \
--js test1.js --js test2.js \
--property_map_input_file prop.in > min.js
4.- Now in your html, include min.js and jquery-1.4.3.min.js. The application should be functional but your code should be faster and smaller.
This will minify your code, not jquery's.
As I said, I have tested this in a small app. If somebody has a bigger and complex app, it would be nice to know that this works.
Thanks,
heg
Have you considered using externs. As far as I know that is the way to go to keep the jQuery methods from being shortened in your code. Externs for jQuery exist as contributions to the closure project.
For jQuery UI you might want to try this. It is something I came across once but haven't tested it myself
BTW: If you're interested, there is this extremely handy build tool for closure: Plovr. I use it all the time and I made externs work with it.
Related
I am trying to add Closure as an external library in PyCharm.
These lines demonstrate where I installed closure:
Chriss-MacBook-Pro:closure chris$ pwd
/Users/chris/DevLibrary/closure-library/closure
Chriss-MacBook-Pro:closure chris$ ls
bin css goog known_issues
I've tried adding various directories in the edit libraries dialog such as:
/Users/chris/DevLibrary/closure-library/
/Users/chris/DevLibrary/closure-library/closure
/Users/chris/DevLibrary/closure-library/closure/goog
I've also tried adding the individual files.
But every time my File Watcher runs I still get:
java -jar /Users/chris/Projects/housemaps/compiler.jar
--compilation_level SIMPLE_OPTIMIZATIONS --js housemap.js housemap.js:1: ERROR - required "goog.dom" namespace never provided
goog.require('goog.dom'); ^
1 error(s), 0 warning(s)
The external libraries feature of Jetbrains is for providing your IDE with access to the source code (for code completion, error checking, ect) for Javascript files that are not included with your project, but are going to be hosted externally.
Closure is not designed to be hosted externally as it is supposed to be used with the closure compiler.
I'm in the process of migrating a project from jQuery to Closure. I have some code that is only half-migrated that I would like to compile. The uncompiled source works fine. I want to know what compile command to compile it using SIMPLE_OPTIMIZATIONS.
The compile command for the original jQuery-based code was this:
java -jar ~/closure/closure-compiler/build/compiler.jar \
--js ~/Sites/mysite/js/bc_school6_2.js \
--js ~/Sites/js_common/bc.job_school.js \
--js ~/Sites/js_common/bc_help.js \
--js ~/Sites/js_common/validation.js \
--js ~/Sites/js_common/md5.js \
--js ~/Sites/js_common/chosen.jquery.js \
--js ~/Sites/js_common/jquery.reveal.js \
--js ~/Sites/js_common/printArea.js
> ~/Sites/mysite/js-minified/bc_school6_2s.js
The SIMPLE_OPTIMIZATIONS compile command for the source when it is fully migrated will be this (although the fully-migrated code will use ADVANCED_OPTIMIZATIONS):
closure-library/closure/bin/build/closurebuilder.py \
--root=closure-library/ \
--root=closure-templates/javascript/ \
--root=bc/ \
--namespace="bc.bc_school6_2" \
--output_mode=compiled \
--compiler_jar=closure-compiler/build/compiler.jar \
--compiler_flags="--compilation_level=SIMPLE_OPTIMIZATIONS" \
> ~/Sites/mysite/js-minified/bc_school6_2s.js
At present, the namespace is not properly set up in the source, so the latter compile process won't work properly.
Is it possible to compile the source using the Google Closure library, but then add in all my jQuery files from js_common folder? Can I do it in one compile command, or if not, can I compile my goog code, and then incorporate the jQuery material?
Thanks.
You can compile your goog code and then include the jQuery code as external code. This method will also let you compile your code in ADVANCED MODE and still be able to use jQuery in it's original form.
To do this, you will have to use a .js file that contains all of your extern declarations. Then you use the --externs flag to tell the closure compiler where to look for externs. See the sample usage below:
java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS \
--js makeallnotes.js --externs extern1.js --externs extern2.js
To find out more about how to declare externs, see this tutorial. Basically, they are used to tell the closure compiler about an external API or library you are using.
There is actually a jQuery extern file included with the Google Closure source code. Find the version of jQuery you are using on this page.
On a side note, I'd look into using Plovr to build your Closure Project. It lets you use a configuration a file to set all of your build parameters and will save a lot of time if you are building your code often.
I am using Luke Rodgers' Backbone and Underscore externs but cannot work out why _.extend is being modified in the compiled output.
For example in Backbone 0.9.2 the following code (193:195):
if (defaults = getValue(this, 'defaults')) {
attributes = _.extend({}, defaults, attributes);
}
is compiled to:
if(c=r(this,"defaults"))a=f.extend({},c,a);
I used the following compile command:
java -jar compiler.jar
--externs backbone-0.9.2-externs.js
--externs underscore-1.3.3-externs.js
--compilation_level ADVANCED_OPTIMIZATIONS
--js underscore-1.3.3.js
--js backbone-0.9.2.js
--js_output_file compiled.js
If I include another JavaScript file:
--js test.js
that contains the following:
_.extend({}, {name: 'test'});
it is unmodified in compiled.js.
Does anyone know why calls to _.extend in backbone.js are being modified?
Glad you've found my externs files useful. Off the top of my head, I believe the issue you are encountering is due to the fact that you are both using externs files AND compiling the libraries.
Typically externs files are used when the library is not part of the compilation procedure. Some people may just use pre-compiled versions of (e.g.) jQuery, Underscore, etc., or link to the shared Google libraries to take advantage of pre-cached js, yet still want to make Closure Compiler understand the jQuery and Underscore API, and so they use externs.
If what you're looking for is the explicit type annotations in the Underscore and Backbone libraries, this is a somewhat different problem.
I want to use the google closure compiler on the javascript source we're using.
In development mode we tend to break functionality to lots of files but for production would like to have them combined into modules.
When calling the compiler I can give it a list of files to include for compilation, but the output of that shows that the compiler did not save the order of the files list.
I searched about it and found that I can use goog.provide/good.require in order to control the dependencies between the different js files.
The problem with that is that it adds code to my js which I just don't need or want, for example:
goog.provide("mainFile")
will add this:
var mainFile = {};
to the compiled js file, something that I don't want.
We're not using the google closure library at all, all I want to use is the compiler.
Is there a way to tell the compiler the order of the files without including more "closure library" functionality which I have no need for?
I can of course create a tool of my own which will first take all the files, combine them into one which will then be the input of the compiler, but I would prefer to void that if it can be done by the compiler itself.
Edit
The goal is to be able to produce modules like the answer in this thread: Using the --module option in Closure Compiler to create multiple output files
And so I want to add to that the ability to control which files go into which module while also having control on their order.
For now I don't use wildcards, but I plan to do so in the future (if it's possible).
simply "cat file1.js file2.js > combined.js && compile..." is fine, but in our case it's a bit more complicated and we'll have to write a program/script that does that based on some logic.
If we can somehow tell the compiler the order of the files in advanced it might just save the time of implementing such a program.
Thanks.
Closure-compiler's ability to create multiple output files provides a powerful tool to separate input files into distinct output chunks. It is designed such that different chunks can be loaded at differing times depending on the features required. There are multiple compiler flags pertaining to chunks.
Each use of the --chunk flag describes an output file and it's dependencies. Each chunk flag follows the following syntax:
--js inputfile.js
--chunk name:num_files:dependency
The resulting output file will be name.js and includes the files specified by the preceding --js flag(s).
The dependency option is what you will be most interested in. It specifies what the parent chunk is. The chunk options must describe a valid dependency tree (you must have a base chunk).
Here's an example:
--js commonfunctions.js
--chunk common:1
--js page1functions.js
--js page1events.js
--chunk page1:2:common
--js page2function.js
--chunk page2:1:common
--js page1addons.js
--chunk page1addons:1:page1
In this case, you are telling the compiler that the page1 and page2 chunks depend on the common chunk and that the page1addons chunk depends on the page1 chunk.
Keep in mind that the compiler can and does move code from one chunk into other chunk output files if it determines that it is only used by that chunk.
None of this requires closure-library or the use of goog.require/provide calls nor does it add any code to your output. If you want the compiler to determine dependencies automatically or to be able to manage those dependencies for you, you'll need to use a module format such as CommonJS, ES2015 modules or goog.require/provide/module calls.
Update Note: Prior to the 20180610 version, the chunk flags were named module. They were renamed to reduce confusion with proper JS modules. The answer has been updated to reflect the new names.
Update Note 2: There is now a utility to automatically calculate and generate these flags for you: https://github.com/ChadKillingsworth/closure-calculate-chunks
You can also set the output path, for example with:
--module_output_path_prefix ./public/js/
See also:
Using the --module option in Closure Compiler to create multiple output files
Google just released Closure, which is a compiler to minify JavaScript.
On the product site, it says "The Closure Compiler has also been integrated with Page Speed".
How do I use Page Speed to compile my web pages JavaScript with Closure?
(Or, is there a web site that I can simply paste in my JavaScript to have closure minify it?
For a single file it's simple
java -jar $path_to_jar/compiler.jar --js input_file.js \
--js_output_file output_file.js
For a multi-file project you can use calcdeps.py in combination with the compiler.jar
#!/bin/sh$
$CALCDEPS_PATH=/path/to_calcdeps #directory containing calcdeps.py
$JAR_PATH=/path/to_jar #directory containing compiler.jar
$CLOSURE_PATH=/path/to_closure #contains directory "closure"
$CALCDEPS_PATH/calcdeps.py --path $CLOSURE_PATH \
--path . \
--compiler_jar $JAR_PATH/compiler.jar \
--input main_project_file.js \
--output_mode compiled \
> compiled_project_file.js
That way compiler gives meaningful information about type errors, etc. Type errors can be caught at compile time because compiler.jar uses certain JSDoc comments for type information.
Extra compiler flags can be passed to calcdeps.py along with -f or --compiler_flags options
If you want to use advanced optimizations set
--compiler_flags "--compilation_level=ADVANCED_OPTIMIZATIONS"
notice the double quotes and the equal sign - had to use that format in bash
The Closure compiler is now available as a JavaScript application. No need for the Java dependency anymore
There are a few ways to integrate with it. I have done it as part of Rollup
ex:
import rollup from 'rollup';
import closure from 'rollup-plugin-closure-compiler-js';
export default {
entry: 'index.js',
dest: 'dist/build.js',
format: 'iife',
plugins: [
closure({
languageIn: 'ECMASCRIPT6',
languageOut: 'ECMASCRIPT5',
compilationLevel: 'ADVANCED',
warningLevel: 'VERBOSE',
externs: [{src:`
var jQuery;
jQuery.fadeIn = function() {};
var ko;
ko.applyBindings = function(vm) {};
ko.computed = function(a,b) {};
ko.observable = function(a) {};
`}],
})
]
}
More info here:
http://www.syntaxsuccess.com/viewarticle/using-the-closure-compiler---advanced_optimizations
"Page Speed 1.4 Beta integrates the Closure Compiler to minify JavaScript files automatically. However, you will need to download and install the Page Speed Beta and Closure Compiler separately."
http://code.google.com/speed/page-speed/download.html
I haven't installed this version yet, but I'm fairly certain that Page Speed will present you with compiled code in its optimization recommendations.
It seems that Closure Compiler is integrated with Page Speed only for Windows.
Use the closure compiler with PHP (hosted via CURL or local via command line tool)
http://bohuco.net/blog/2009/11/google-closure-compiler-with-php/
If you need to compile multiple js files or if you would like to simplify compilation process, you may use kjscompiler: https://github.com/knyga/kjscompiler (based on google closure compiler)