Underscore.js externs for Google Closure Compiler - javascript

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.

Related

Jetbrains adding Closure as an external library

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.

How to include minified library version in RequireJS optimization

My situation is as follows:
My project based on RequireJS.
I am using RequireJS Optimizer for to create a single JS file.
Some of the module use a certain third party library as a dependency.
The third party is NOT included in the optimized file (libName: empty
in the build config).
RequireJS is configured through var require = {} object which appears
on EACH PAGE, right above the RequireJS. The object defines a path to
the unminifed version of the library, among other things.
What i'd like to achieve:
Use the same config file in both development and production (the require={} object is included with tag on each page). During development I'd like modules to use the UNMINIFIED version of the third party.However, after optimization occurs, i would like all the modules to use the minified version of that third party.
I did think of a solution in theory, but it seems a bit messy and Im hopeful cleaner solution exists:
To have the runtime config point to unminified version
var require = {
paths:{
'thirdParty':'lib/thirdParty'
}
}
Create a module which execute (lets call it "PathRewrite" Module):
requirejs.config({
paths:{
'thirdParty':'lib/thirdParty.min'
}
})
In runtime configuration, define path to "PathRewrite" as empty
var require = {
paths:{
'thirdParty':'lib/thirdParty',
'PathRewrite':'empty'
}
}
In the build configuration file define a real Path to "PathRewrite" in order for it to be included in the "main" file (concatenated file after build).
Include "PathRewrite" as a dependency of a module which is executed first.
What I hope that will happen is that during dev, when optimized file is not used, PathRewrite is will not be used, hence the path to unminified third party in the runtime config will be used.
When the project is optimized, PathRewrite will be included and executed. According to RequireJS documentation, it is possible to run RequireJS configuration twice and the configuration will be appended/overwritten. PathRewrite execution will overwrite the path to "thirdParty" to minified, which will thus be used by all the modules.
Hopefully i've provided enough information. I'd be glad hear of other ways to get this done. Thanks in advance.
This topic appears to have been explored a bit in this answer:
Loading min.js files Generated by TypeScript with Require
Don't let the title discourage you. Typescript is not the core issue of the question being answered there. Unfortunately, the discussion reveals that the RequireJS optimizer may be the only way to get decent minification to work, as it seems incapable of selecting alternate paths properly.
Why don't you want to use inbuilt RequireJs optimizer? You may just include this option
optimize : "uglify2"
and all your and third-party code will be minified after concatenation. In this case you don't need to use minified versions of third-party libraries.

How do I split my javascript into modules using Google's Closure Compiler?

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

Closure compiler app using jquery

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.

How to use Google's Closure to compile JavaScript

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)

Categories