closure compiler externs for Dojo toolkit and dgrid - javascript

Does anybody have to share a file for extern definitions for dojo and dgrid ?
I am trying to include those in my clojurescript project and to use even 'simple' clsure compiler optimization option.
At the moment I have found dgrid and dojo toolkit incompatible with Clojurescript compilation process.
In other words it is not possible to
a) include dojo or dgrid with :foreign-libs option and then leverage the
closure compiler to create a 'minified release using closure compiler :advanced or even :simple option
b) it is also not possible to include the dojo or dgrid libraries with :extern option
because for that one has to create a list of extern definitions (which does not come in dojo/dgrid releases).
I am pretty sure option ( a ) is a dead-end, because for it to work dojo team needs to make changes to the toolkit, and it is probably low priority. I have read Stephen Chung's 50+ pages document of how to modify dojo to work with google-closure, but it is well beyond my capabilities to re-implement for Dojo 1.9 and above.
I am thinking ( b ) might eventually work, but for that I need to find the externs library.
Hoping somebody has done it for dojo 1.9 and the latest dgrid.
Prior to posting here I had checked the repository of currently available 'externs' for the closure compiler,and dojo is not there
https://code.google.com/p/closure-compiler/source/browse/#git%2Fcontrib%2Fexterns
I had also found a online extractor of externs
http://www.dotnetwise.com/Code/Externs/index.html
and http://www.dotkam.com/2013/07/15/clojurescript-use-any-javascript-library/
However, I am not even sure what dgrid/dojo files to do this for.
Therefore looking if anybody has created these externs already.

You can use their own source file as the externs definition. Obviously this means that the compiler can't optimize the library, but if as you say, you don't need that, it's a good working option.

I am not experienced with dojo/dgrid in ClojureScript but I've used several javascript libraries with ClojureScript already.
The best way to use complicated libraries with ClojureScript is just not to touch them, and not run Google Closure on them. (what you call (b)).
Therefore, you will need to put very few externs definitions in externs.js
Only for the specific vars/functions which you access from your ClojureScript code. You don't need externs.js for EVERYTHING they declare.
The Google Closure compiler will run only on your code, not the external js library.
You need to put externs only when you:
1. Call your cljs function from js code (to avoid calling a munged function name that is not what you have in your js)
2. Call the js library function from your cljs code (to avoid having munged the function name in the function call).
So there's no prior work that needs to be done, you need to put a small externs file exactly for the specific calls you make.

Related

How to use react-apollo in clojurescript that survives advanced optimization?

I am building a clojurescript application that depends on react-apollo to interact with third party graphql API. Since I could not figure out a way to load the library with all dependencies externally, I opted to npm install it and let the whole dependency get compiled by closure compiler. This did not work out of the box and required fork-and-patch on some js dependencies that confuses google closure compiler due to mix of ES6 and CommonJS require/import.
With advanced optimization, I was only able to get things working after fishing out renamed properties in the js debugger. And I'm sure my extern file does not have everything. I also need to make sure all properties are addressed by string in clojurescript, I think graphql creates object based on string in the query.
With string keys, things like destructuring don't work. Transforming objects with js->clj :keywordize-keys true and back seems to rename properties unless I add every keyword to the extern file.
I tried setting *warn-on-infer* and :infer-externs, but the generated extern has very few entry. Not sure if I'm using it right.
Advanced optimization seems like a must though, it's 461K vs 3MB with simple.
TL;DR
Tried to use npm lib in cljs, issues with advanced optimizations. What is the best practice to use these libs?

How to distribute a library which uses Closure-library without including any of the actual Closure-library source?

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.

How do you attach JSdoc in Eclipse so that I can have autocomplete for a personal library

I have a JavaScript library that I am working on currently. I have structured it into lots of files and I use the module approach to define each 'module'.
var ns = generateNamespace("me.mycompany.mypackage.MyFile");
(function (ns, undefined) {
// some module
}(ns));
The modules are dynamically named using a namespacing function meaning that autocomplete is almost impossible as things stand (unless Eclipse can run my code and figure out the namespaces, Visual Studio can!).
Therefore I intend to generate JSdoc for my project in the hope that if I include this into Eclipse (somehow) Eclipse can use this to give me content assist.
Firstly I do not know if this is possible... however I think that it is as I can see that it is maybe how this works? However I tried to follow this along and struggled to get something working, by this I mean it didn't work. The interesting info from the link:
"JSDT libraries are collections of JavaScript source files that have prototyped object/class definitions and JSDoc. The inference engine then models these libraries... making them available to every JavaScript file in the project... Bindings for nonstandard and future runtimes are similarly easy to create... add the... library to their project and gain content completion and hover help"
I know how to write JSdoc annotations and I know how to generate JSdoc using one of the various tools.
What I need therefore is instructions on how to include JSdoc (as a library maybe) in Eclipse so that it will give auto complete for the stuff in the JSdoc.
Previous answer:
You can also run jsdoc_toolkit from within eclipse by setting up Run -
> External Tools -> Open External Tools Dialog...
Location
C:\Program Files\Java\jre1.5.0_12\bin\java.exe
Working Directory
C:\DirectoryToWhereJsDocToolkitIsLocated\jsdoc_toolkit
Arguments
-jar app/js.jar app/run.js -r=4 -t=templates/htm "-d=C:
\PathToWhereDocIsSaved" "C:\PathToWebsiteToDocument"
For more about the arguments check the jsdoc_toolkit documentation.
Have fun
Simon
Taken from this Google Groups thread.
Updated Answer:
Eclipse JavaScript Editor: content assist for js files, autocompletion
Disclaimer, I'm the author of tern.java.
I suggest you that you install tern.java. It provides a JSDoc support. Once you have selected this support, you can benefit
with completion :
and soon with validation:
This support is not perfect but it starts working.
I am not using it by myself, so I'm not sure if it works, but there exists a grunt-plugin for jsdoc3. Grunt is supported by Eclipse. So maybe it helps.
Grunt-PlugIn in npm

Custom dojo build at functions level

We are creating a javascript library from scratch and we need some utilities functions, just like what dojo provides, e.g. xhr wrapper, simple inheritances and array manipulation, etc. We don't want to write these functions ourselves from scratch, but we also don't want to just copy and paste code from dojo.
Dojo provides the custom build mechanism, but it works on the module level. For example, in the custom build, you can specify to only add the lang module in the dojo base. But we may only need the dojo.hitch function in the lang module, but not the dojo.clone function that also included in the lang module. We have a tight constraint on the size of the library file, so we need to remove any unused code.
What we are seeking is a way to extract certain functions from a module and build these functions into a single javascript file. For example, say we need dojo.mixin, dojo.declare and dojo.hitch functions, then these functions' declaration and their dependent inner functions should be built into a single file.
Any suggestions?
Update from my test result
Thanks Stephen Chung for your great suggestion on how to solve this problem.
So basically I created a custom dojo build with four modules : dojo._base.xhr, dojo._base.json, dojo._base.declare and dojo._base.lang. The built dojo.js file is 149kb, after using Google Closure compiler with advanced mode, the size has reduced to 24kb and the unused functions have been removed. If we want to keep some functions, just add another javascript file like below:
window['dojo'] = dojo;
window['dojo']['requireLocalization'] = dojo.requireLocalization;
window['dojo']['moduleUrl'] = dojo.moduleUrl;
and compile it with dojo.js.
Unfortunately the size is still a little bigger. We have a size limit of 40k in total. But this is still a very good solution for other cases.
Dojo Core is written in a very compact manner, with a lot of cross callings (i.e. one function calling other functions) in order to save download bytes and reduce code size.
Therefore, you need a minimal set of Dojo Core functions, together with the functions that it calls.
In other words, what you need is a build that includes Dojo Core, but then removes any dead-code that is never called.
I'd suggest that you don't go about creating a minimal-footprint library by writing it from scratch yourself. What you need is to use the Closure Compiler's Advanced Mode to process your Dojo application. It removes dead code, optimizes the entire app, and fully obfuscates it.
And yes, it is possible to use the Closure Compiler with Dojo in Advanced Mode -- Dojo is probably the only popular library that can do it. Read it here.
Some statistics: A Closure-compiled Dojo app is typically around 25-30% smaller than the equivalent Dojo app in a Shrinksafe build. It depends on how many Dojo Core features you use -- typically you may reduce Dojo Core up to 40% of the original size (i.e. reduce code size by up to 60%) from dead code removal alone. Further reductions are more difficult, as you may have to start removing features like the Dojo loader etc.
Are you fixed on dojo? Google's closure library offers a very similar package management system to dojo, as well as all the necessary scripts and tools you need to compile the javascript down to a single "executable". The closure library compiler is arguably one of the most advanced javascript minifiers you will find so if tight, concise javascript is your goal, this tool could help tremendously.

Is it possible to use Closure Compiler ADVANCED_OPTIMIZATIONS with jQuery?

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

Categories

Resources