Google Closure: goog.require in Play 2.2.1 - javascript

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

Related

Import, Require? How to Mash Javascript Files Together?

This is vague - I apologize in advance, I am trying to be as succinct as I can with my limited understanding, while exposing my potentially incorrect assumptions.
I have a website that's literally one huge HTML file. It runs scripts defined in-line in a <scripts> tag.
My goal is to move all the scripts into individual .js files and pull them into index.html (or into one another where required). I am familiar with the usage of Node's require and I am familiar with import, as used in Angular. I stress usage because I don't really know how they work.
Assumption 1: I cannot use require - it is purely for Node.js. The reason I bring it up is that I am pretty sure I have seen require in AngularJS 1.5 code, so assuming makes me uncomfortable. I am guessing this was stitched together by WebPack, Gulp, or similar.
Assumption 2: I should use import, but import only works with a URL address, if I have my .js hosted on a server or CDN, it will be be pulled. BUT, I cannot give local pathing (on the server) here - index.html will NOT automatically pull in the dependencies while being served. I need npm/Webpack/other to pre-compile my index.html if I want the deps pulled in on the server.
Assumption 3: Pre-compiling into a single, ready-to-go, html file is the desired way to build things, because the file can be served quickly (assuming it's ready to go). I make the assumption with the recent trend of serving Markdown from CDNs, the appearance of the JAMstack, and the number of sites using Jekyll and such (though admittedly for traditional Jekyll sites).
Assumption 4: I also want to go to Typescript eventually, but I assume that changes nothing, since I will just pull in TS to compile it down to .js and then use whatever solution I used above
Question: If it's clear what I am trying to do and what confuses me, is a decent solution to look into npm/Webpack to stich together my .js files? What would prepare them for being stiched together, using import/export? If so, is there an example of how this is usually done?
As you mentioned, require cannot be used for your purposes, since it is a part of CommonJS and NodeJS's module system. More info on require can be found here: What is this Javascript "require"?
Import is a ES2015 standard JS syntax. But ES2015 standard and everything above it has very limited browser support. You can read more about it here: Import Reference
However, you can still code in the latest standard (thereby enabling the use of import/export etc.,) and then transpile the code to be able to run on the browser. Inorder to do this, you require a transpiler. You can refer Babel which is one of the most popular transpilers : https://babeljs.io/
For your exact purpose, you need to use a module bundler. Webpack/Rollup etc., are some popular module bundlers. They can automatically identify all the JS files referenced through import, combine them and then transpile code to be able to run on the browser (they also use a transpiler) and produce a single JS file (or multiple, based on your configurations).
You can refer the getting started guides of Webpack: https://webpack.js.org/guides/getting-started/
or RollupJS: https://rollupjs.org/guide/en#quick-start

Using .js file extensions whilst writing scripts that return jsx

I started using react as my ui framework of choice. Upon my adventure through the documentation I noticed that when using the create-react-app script to spin up a new react boilerplate, they used .js file extension on scripts that where returning jsx code. When I asked my buddy he told me that you should use the .jsx extension on scripts that are returning this kind of code.
Im a bit lost here as if both works, wouldn't it just be better to go with the .js extension as at the end of the day its javascript we writing.
Please help me with what is considered best practise. (I kinda have a feeling it would be to use the .jsx extensions on these types of scripts, but I'd love to hear the community's view on this)
Thanks in advance :)
It's really up to personal preference.
My personal opinion is JavaScript is JavaScript, and I just use .js. Others will prefer to use .jsx in files that are JSX and .js in for things like utilities, in order to differentiate. The only important thing is to be consistent in whatever you choose (at least within one project).
In general, it doesn't matter.
The only time it might actually matter is based on your build pipeline. Some build pipelines may be configured to compile .js and .jsx with slightly different rules, but that would be based on your application (things like create-react-app don't care).
At the end of the day, you could use a .cookiemonster extension and it'd work just fine (as long as your build pipeline is configured to handle it).
Actually it doesn't matter, is up to you to decide I prefer to use .jsx when I return the mix between HTML and JS and use .js only when I'm using plain JS or ES6.
I recommend you to read about this on this issue on github.

Can we create externs from a full .js file with Google Closure Compiler?

I'm wondering whether extern files for the Google closure compiler need to be written by hand. I have not seen anything about the possibility of generating those files from my .js files. It's quite a bit of work to create all the externs by hand and it is error prone too (i.e. wrong parameter definitions as it changes with time...)
So I was wondering whether there was a Linux tool (command line) for that purpose. If not, would there be a way to compare the .js against the extern files so I can at least make sure they are in sync.?
http://www.dotnetwise.com/Code/Externs/ aims to do this but I haven't used it myself so I'm not sure how well it works.
We have an issue open to do this as part of the compiler but I don't expect that it will happen anytime soon.

How do I configure paths to my javascript files in the Jasmine / Maven autogenerated ManualSpecRunner.html?

I think the question says most of it. I have an autogenerated ManualSpecRunner.html file as created by maven / jasmine plug-in and I've got it to put itself into the deployable .war by using:
<jasmineTargetDir>${basedir}/pathForMyWebapp</jasmineTargetDir>
However, all the links to js files within the ManualSpecRunner.html are hard coded file:/// references - this is a bit mental, I want them to just be the relative paths to the files that are also in the webapp i.e.
Currently it gives me this path:
file:///home/username/code/HEAD/pathForMyWebapp/js/yui.js
whereas I need it to have the far more simple
/pathForMyWebapp/js/yui.js
I have tried changing two other variables in the maven script, but neither seems to have the desired effect, neither of these configuration options do what I need, the second having seemingly no effect:
<jsSrcDir>/pathForMyWebapp</jsSrcDir>
nor
<jsTestSrcDir>/pathForMyWebapp</jsTestSrcDir>
I've looked through the documentation but think I must be missing something (also, more notes on various config params listed in https://github.com/searls/jasmine-maven-plugin/blob/master/src/main/java/com/github/searls/jasmine/AbstractJasmineMojo.java are meant to do would be helpful so I can work out if I'm doing it wrong or if it's not possible!)
Any suggestions?
[p.s. I've changed some of the path names as they've got sensitive info in them, so please ignore their oddness!]
I think I understand the source of your confusion. It looks like you're trying to direct the target of the jasmine-maven-plugin to a directory inside your project's packaged *.war file so that you can run your specs against the code after it's deployed to a server, is that correct?
Unfortunately, the plugin wasn't designed with that use in mind. The jasmineTargetDir directory is usually left at its default value of target/jasmine and wasn't intended to be bundled with your application (it's analogous to the target/surefire-reports generated by maven-surefire-plugin for Java unit tests). So the reason that the script tags in ManualSpecRunner.html point to invalid locations is because that file is generated in order to be run from the local filesystem in a browser from the workstation that's building the project (to facilitate TDD).
All of that to say, if I'm reading your intention right, I think it'd be a cool feature to build a third spec runner that could be deployed with the app and executed remotely. (Especially if the project's Jasmine specs are functional/integration as opposed to isolated unit tests.) Unfortunately that's not something the project does yet.
I'm afraid that for now, if you needed to bundle the jasmine tests and execute them on the deployed server, you would need to copy ManualSpecRunner.html and jasmine into your src/main/webapp, fix the script tag references, and then manually maintain it as files are added and removed.
Make sense?

How to cleanup unreferenced Javascript libraries

Our project has more than 300 JSP files and more than 200 JavaScript files. I'd like to do some cleanup, removing unnecessary JS files. Even if the JSP includes the JS maybe none of the functions are used. The goal is to reduce both complexity and time needed to load the page. My IDE is Eclipse. Giving the dynamic nature of JavaScript I guess it will be hard or even impossible.
If it's conceivable that the application can be tested with a lot of coverage (i.e. going through every dialog, error message, and situation imaginable) you may be able to work with your access log files - compare the list of JS files to those fetched after period x of heavy use.
An alternative implementation of this would be setting up a "honeypot" (see my answer to this question).
Both these methods are of course "soft" in that their quality relies in how throroughly the application is actually used during testing time.
If you have any way of grepping all script references, that would be preferable. Maybe you can do a global search on {anything}.js, that would match most ways how to embed a JS file.
To find out what functions and javascript files are used in a project, you need code coverage tools, like JSCoverage or Code coverage for Firebug. These tools will return the functions used and the files used. Using these with an automated test suit like the Selenium or randomized testing should give you a fairly good idea which files are loaded.
If the files are loaded dynamically, you can also use Firebug or Fiddler to log the requests for the JS files.
Unfortunately if you want certainty, not just extremely high likeliness that you get with the above tools, you would have to generate a calling graph for your entire webapp, maybe using a Javascript Compiler, like Rhino...

Categories

Resources