Untangling JS Source from Closure Compiler - javascript

There is a javascript application I would like to modify for my use*. The problem is, the js is compiled with Google Closure Compiler. Obviously, I should modify the sources (which are available in the repository), and re-compile.
This is my first encounter with GCC. I skimmed the documentation and came to the conclusion that the key is using the sources mentioned in deps.js via goog.addDependency keywords.
So I set up an HTML file and referenced all the sources. Loading this file I got 118 ReferenceError: goog is not defined errors in firebug console.
Then I read some more and found the app has been compiled with the help of kbuild, and that it uses a config file, config.kb, to send the right parameters to GCC. This file, indicates the first file should be loader.js, so I reordered the <script> tags and moved
<script type="text/javascript" src="./eightball/loader.js"></script>
to the top. but the same errors are thrown. So, what is missing?
* The license is MIT and there is no issue with the rights.

First, it would seem the application is using Google Closure, which is a JavaScript library developed by Google.
This is (of course), completely different to Google Closure Compiler, which is a JavaScript minification and obfuscation engine (dang these large companies and their quest to name everything the same).
That means you should include the Closure bootstrap before deps you've got listed; which is what the application itself does, as in the main view, it calls the game_js helper, which includes the base file of Closure if the application hasn't been compiled.
TLDR:
Try including the /javascripts/closure/closure/goog/base.js file first.

Related

Autocompletion for VSCode for a module imported via <script src>

Issue description
I would like to have Visual Studio Code to hint autocompletion and provide documentation for a JavaScript project which includes libraries a module in a separate HTML file.
Context
I am using P5JS. It assumes we include the P5JS library and our script via the <script src="…"> tag in an HTML file. Autocompletion and documentation work after installing the p5.vscode extension. So, no problem here.
I am also using ml-matrix, which I'm including in the HTML via the <script src="…"> tag. The library constructors and methods can be accessed via mlMatrix.. (I figured this by toying around in the console, and I wouldn't know otherwise how to find out I need to prepend mlMatrix. to all functions in the library.)
index.html
<head>
<!-- script src="…" P5JS libraries -->
<script src="./node_modules/ml-matrix/matrix.umd.js"></script>
</head>
<body>
<script src="./script.js"></script>
</body>
script.js
A = mlMatrix.Matrix.eye(3) // no autocompletion or docs, code runs
console.log(A)
Workaround
Adding import * as mlMatrix from "ml-matrix" to the beginning of script.js makes autocompletion and documentation work, but the overall project does not run. So, I have to comment and uncomment the first line every time I save and preview my edits on the browser.
script.js
import * as mlMatrix from "ml-matrix"
A = mlMatrix.Matrix.eye(3) // autocompletion and docs work, code doesn't run
console.log(A)
When loading the HTML, the browser complains with script.js:1 Uncaught SyntaxError: Cannot use import statement outside a module..
Desiderata
I'd like to be able to save and preview my project while having a working autocompletion and documentation hint from VSC.
Debugging
After reading a few sections of David Flanagan's «JavaScript: The Definitive Guide», I started figuring out what's going on. So, I'm reporting here my current understanding.
JavaScript, or rather ECMAScript, used to be a scripting language.
Scripts loaded with <script src="…"> are "global" scripts, living on the current page, injecting vars and functions in the global scope (or window object).
In order to support proper software engineering relying on modularity, modules were introduced in 2015, in ECMAScript 6, or ES6 in short. To import a module in an HTML document one can use <script type="module" src="…">.
Now, to import a module in a JS file, the file itself needs to be a module. So, dealing with an actual script myself, I cannot do such a thing.
Even by <script src="…"> a module, it won't inject itself in the main namespace. It will create a whatever name where it will store everything it exports. So, now we are at the point where we need to instruct the IDE that a module has been loaded on the HTML side with a specific name and it's used in a JS script.
So, we have now a more articulate question.
Issue re-statement
How to inform VSC that a module has been loaded through the HTML page?
I believe a probable answer will include some custom jsconfig.json to be created. Right now I have zero clues about how to do this.
Another solution would be using some specific ///<reference path="…"/> at the beginning of the JS file. Also for this I have no specific knowledge.

ClojureScript-Lib and my ClojureScript on same page

Let's assume I have a small web-application and want to use a third-party library that comes with an already compiled version of a ClojureScript.
As a user of that library I have to include that generated Javascript file in my HTML page.
<script src="/javascript/gen/lib.js" type="text/javascript">
So far so good. Everything works fine.
But since my web-application needs some frontend-magic, I wanted to include some ClojureScript of my own. So I wrote a couple of lines, compiled it to Javascript and added another line in the HTML head:
<script src="/javascript/gen/lib.js" type="text/javascript">
<script src="/javascript/gen/my-stuff.js" type="text/javascript">
This is, where it gets ugly. I get this error in the javascript console:
Error: Namespace "goog.debug.Error" already declared.
After googling that error, I get multiple pages, that state, that I can not use multiple Google Closure Compiled things on one page. See SO: Multiple ClojureScript files on same page
So, how do I tackle that situation? On one hand I have an already Google Closure compiled lib and on the other hand my ClojureScript stuff. How do I get one (or two) compiled Javascript files out of this?
Would it be easier, if that third-party lib would provide a non-compiled ClojureScript version?
Yes, it would be easier if the third-party library would provide a non-compiled ClojureScript version. Then you would require it and use it from your code and compile everything together. The ClojureScript compiler with require each dependency once (even the shared dependencies) and the Google Closure compiler would do its optimization pass over all the code.
Try to find the library in Clojars or package it as a jar to consume it from your existing ClojureScript setup. (If the library is open source, give us a link and we'll help you out)

Why using jquery map?

Why using jquery.min.map if:
jquery = 242 ko
jquery.min + jquery.min.map = 83 + 125 = 208 ko (the map is even greater than the library)
And if we remove the comments, we will get a small jquery that could be easier to read (and to debug).
So, why using the map if it will only add more than 100 ko and an extra request?
What is the best practice?
Source maps are loaded only when the developer tools are active. Browsers won't load them for application's users.
Edit: It should be mentioned that there are 2 types of source maps. One which is an external file and there is a link to it in the actual file and another one which is embedded in the main file. Browsers actually have to load the entire file (i.e. including the embedded source map) for the second type.
Check https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ for more information.
That's called a source map. This answer goes into detail about what they are, how they work, and why you would want to use it.
EDIT
Extracted answer from the above SO link for posterity. Answered by #aaronfrost
The .map files are for js and css files that have been minified. They are called SourceMaps. When you minify a file, like the angular.js file, it takes thousands of lines of pretty code and turns it into only a few lines of ugly code. Hopefully, when you are shipping your code to production, you are using the minified code instead of the full, unminified version. When your app is in production, and has an error, the sourcemap will help take your ugly file, and will allow you to see the original version of the code. If you didn't have the sourcemap, then any error would seem cryptic at best.
Same for CSS files. Once you take a SASS or LESS file and compile it to CSS, it looks nothing like it's original form. If you enable sourcemaps, then you can see the original state of the file, instead of the modified state.
What is it for?
To de-reference uglified code
How can a developer use it?
You use it for debugging a production app. In development mode you can use the full version of Angular. In production, you would use the minified version.
Should I care about creating a js.map file?
If you care about being able to debug production code easier, then yes, you should do it.
How does it get created?
It is created at build time. There are build tools that can build your .map file for you as it does other files. https://github.com/gruntjs/grunt-contrib-uglify/issues/71

Google Closure: goog.require in Play 2.2.1

I've been beginning a new Play project using Play v2.2.1 and am having difficulty getting the Google Closure compiler to properly handle goog.provide and goog.require statements. All of my Javascript files are in the app/assets folder and are being served up properly using Play's reverse routing. However, any time I try to use goog.require(_namespace_), I get the compilation error "required namespace namespace not provided yet." This happens whether I link to just the file with the require or both the requiring and providing .js files in my view template. However, it does not happen if I link to the minified version of the requiring file.
For the most part, the closure compiler seems to be working; for example, the .min.js files do exist (even if they don't actually seem to be getting minified, but that is probably a separate issue). I haven't changed any build settings in my Play project.
The Play documentation on using the Google Closure compiler for Play 2.2.x does not directly reference using goog.require() and goog.provide() for Javascript dependencies. It does, however, give a link to using RequireJS to do the job. Is there no way to take advantage of the Closure compiler's require system?
As a disclaimer, I am not very experienced with the Closure compiler. I have used it at work where we minify all of our Javascript to one file, so all I know is basically what result I expect to see. I was hoping Play would have taken care of most of the dirty work of making everything "just work", but it doesn't seem as straightforward as I'd hoped and I haven't had any success solving the problem after a few hours of scouring the web.
There is a plovr plugin that Benn McCann did based on some stuff I posted on the play mailing list a long time ago, which from what I remember was created because of this exact problem, maybe you could use that: https://github.com/benmccann/play-plovr-plugin

Referencing javascript embedded resource but intellisense doesn't show anything

I'm stuck... I'm trying to reference a javascript file that has been embedded inside a third party assembly, but it doesn't seem to work:
What I've done:
I have a folder RefAssemblies where this library DLL with embedded javascript file is located
I added a project reference and pointed to this library assembly
I added a line in my javascript file where I want the reference to work ie.
/// <reference name="ScriptName.js" assembly="AssemblyName" />
I tried naming my assembly with name only, and also with full assembly name including name, version, culture and public key token. No difference.
Added my library assembly to my project's web.config inside system.web\assemblies (AFAIK that's the part where you have to add your assembly and make it well-known in your application) so I should be able to access it without referencing assembly at all just resource name. No difference.
And yes I was pressing the Ctrl+Shift+J after any change I've done so Visual studio refreshed Javascript intellisense cache. I even unloaded and reloaded my web project after I changed web project's web.config. Just so that Visual Studio would read the file and reload everything anew.
But still unlucky... And I'm not getting any Javascript Intellisense errors in the General output window either...
I must be missing something...
Additional note:
It may be helpful to know that I'm running ReSharper 6.1.1000.82 within Visual Studio 10.0.40219.1
Other things I've done afterwards
Uninstalled ReSharper from my machine
Reset Visual Studio by running it from command prompt using
devenv /ResetSettings
No luck either.
Do you have any other suggestions I might do?
I'm also having odd problems with embedded resources. I have managed to get it working though by using the fully qualified resource name. You can find that out by using ilspy to open the assembly and then select the Resources folder, then the full name of all the resources will be displayed.
As i said i have gotten this to work in one solution, but in others it doesnt work and i have no idea why.. the non working solution has a diffrent structure where the diffrent assemblies are in diffrent folders, but i have nto been able to isolate that as the cause..
-edit-
After much trial and error it seems like the key thing to making embedded javascript references work is to set the output folder for the project containing the reference to bin and not bin\debug.
from what i can gather, there are no other settings or assembly references that affect the embedded resources, only the output folder of the project that has the reference. i'm guessing that the javascript language service is unable to find the assemblies with embedded resources unless they are in the private path or the gac, but i have yet do understand exactly where this binpath is set.
i've tried setting it on the project itself and on what i think is the actual language service exe, but to no avail.
i made a connect issue here:
https://connect.microsoft.com/VisualStudio/feedback/details/770185/js-references-to-embedded-files-require-the-referencing-project-to-have-outputpath-bin

Categories

Resources