Play 2.3 requireJs optimization and shim for multiple modules - playframework-2.3

This is my current setup for Play 2.2.x requireJS. Will it continue to work after 2.3? I can't find requireJs or requireJsShim anywhere in the 2.3 documentation.
requireJs ++= Seq("mainAccount.js", "mainOrg.js", "mainPublic.js"), // This tells Play to optimize this file and its dependencies
requireJsShim += "build.js", // This tells Play to read the RequireJS "shim" configuration from build.js
requireJsFolder := "js"

Instead of requireJs use:
RjsKeys.modules := Seq(
WebJs.JS.Object("name" -> "mainAccount"),
WebJs.JS.Object("name" -> "mainOrg"),
WebJs.JS.Object("name" -> "mainPublic")
)
Instead of requireJsShim use
RjsKeys.mainConfig := "build"
I think you can just omit requireJsFolder as baseUrl is considered to be either js or javascripts by default. See here: https://github.com/sbt/sbt-rjs/blob/master/src/main/scala/com/typesafe/sbt/rjs/SbtRjs.scala#L104
If you want to change to something else, then use RjsKeys.baseUrl := "your-js-dir-name"
Also there is a github project using RequireJS that was migrated to Play 2.3, may be useful as well:
https://github.com/mariussoutier/play-angular-require-seed
For more details check sbt-rjs plugin docs:
https://github.com/sbt/sbt-rjs

Related

How can I stop the ClojureScript compiler from resolving certain `require`s?

In my ClojureScript code I am requiring a JavaScript module called seedrandom which is in the node_modules folder, like this:
(ns something.core
(:require ["seedrandom" :as rnd]))
(js/console.log (.quick (rnd "x")))
According to the seedrandom documentation it is intended for both nodejs and the browser, and I've previously included and used it successfully in ClojureScript code via a <script> tag, confirming it works in the browser.
Running this cljs file in lumo on the command line works well and outputs a deterministically random number.
When I try to use this same cljs file in my Reagent frontend project I see the following error:
Compiling build :app to "public/js/app.js" from ["src" "env/dev/cljs"]...
events.js:183
throw er; // Unhandled 'error' event
^
Error: module not found: "crypto" from file /home/chrism/dev/something/node_modules/seedrandom/seedrandom.js
at onresolve (/home/chrism/dev/something/node_modules/#cljs-oss/module-deps/index.js:181:30)
...
Inside seedrandom.js we see the following:
// When in node.js, try using crypto package for autoseeding.
try {
nodecrypto = require('crypto');
} catch (ex) {}
Clearly this code is intended to ignore the built-in nodejs crypto module when running in the browser. The problem, as far as I can tell, is that the ClojureScript compiler does not know that - it sees that require('crypto') and tries to pull it into the compilation phase, but can't find it because it's a nodejs built-in.
Is there some way I can tell the compiler to ignore that particular require? Or can I shim the 'crypto' module somehow? What is the cleanest way to solve this?
Note: I have previously experienced this same issue with JavaScript modules which check for the fs node module. Hope we can find a general solution to use again in future. Thanks!
Relevant versions: [org.clojure/clojurescript "1.10.520"] and [reagent "0.8.1"].
This answer is related, asking a similar question from the perspective of Google Closure, which ClojureScript uses, but I'm looking for an answer I can use specifically with cljs.

AoT + Webpack + json dynamic require

After installing the AoT plugin (https://www.npmjs.com/package/#ngtools/webpack) for webpack, dynamic requires no longer work:
// Example that used to work
public getJson<T>(fileName: String): T {
return require(`../../${fileName}_${this.lang}.json`);
}
With the standard ts-loader or awesome-typescript-loader etc, dynamic requires worked and webpack bundled the json files into the main app bundle. However, with the AoT/Webpack plugin the json files are not bundled at all. I don't even think the aot loader iterates over the json files anymore.
Any ideas how to get this to work again? Thanks.
Info:
https://github.com/angular/angular-cli/issues/3306
https://github.com/angular/angular-cli/pull/4153
Update:
Works somewhat with SystemJS -> System.import() but erratically
https://github.com/angular/angular-cli/issues/6629#issuecomment-336411537
Workaround is to use System.import() to build load and bundle the dynamic files then use the standard webpack mechanism to load the actual files:
public getLazyFiles<T>(somePath: string): T {
/* AoT Hack - causes the AoT to find and prepare the dynamically loaded files */
System.import(`../../${somePath}_${this.someSuffix}.json`);
/* ------- */
// This is then used by webpack to actually load the files
return require(`../../${somePath}_${this.someSuffix}.json`);
}
Why this workaround is needed is explained here: https://github.com/angular/angular-cli/issues/6629#issuecomment-336478854

Using lodash module in babel-node REPL?

I am trying to test lodash, and apparently the following line won't work in the REPL:
import curry from 'lodash/curry';
See, e.g., babel-node es6 "Modules aren't supported in the REPL"
Why does babel-node not support module loading in the REPL?
Is there a way that I can pre-load a module like lodash into babel-node? (e.g. via a command line option or a configuration file)
If not, is there another way of evaluating ES6 with lodash preloaded?
So far, I've tried the online REPL at https://babeljs.io/repl/, and evaluation in the Console in Firefox. None worked.
import surely won't work, because the package should be installed first and bundled in order to be imported, which isn't the duty of Babel REPL.
Lodash is already loaded and used in Babel REPL, it can be used in REPL as _ global:
const { curry } = _;
If the question isn't limited to Lodash, the quickest way to get third-party library in REPL is to load the script manually. And since Babel website has jQuery loaded (as almost any website), the shortest way to do this is jQuery.getScript, in console:
$.getScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js');
After that Lodash _ global becomes available in REPL.
The whole code can be wrapped with callback to skip console part:
$.getScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js', () => {
console.log(_.VERSION);
});
babel-node REPL doesn't support imports, as the links in the original post say. Instead, require should be used, like anywhere else in Node.
var { curry } = require('lodash')
This requires to have lodash installed in node_modules that exists in current working directory.

ClojureScript + boot: make non-CLJSJS libs available to test code?

When using boot for ClojureScript projects, how does one make external non-CLJSJS JavaScript libraries available to test code (vs application code)?
Application code can get access when it's included on the same HTML page as the library.
(With leiningen + figwheel, the test code ran in the same context as the application code -- on my index.html page -- so the test code was aware of the third party js library.)
Is there a similar page context in boot for test code? Or is there a way to conj something like ["resources/third-party/library.js"] onto a source or resource path, such that unit tests can refer to the same library that application code does?
When I run boot auto-test it says #object[ReferenceError ReferenceError: Can't find variable: CodeMirror]. CodeMirror is the third party library in my case. My unit tests need a CodeMirror instance so they can .setValue, then call a bunch of CodeMirror methods to tell the instance what to do, then verify the instance's new value and cursor position. I'm testing whether my ClojureScript comes up with the right calls to CodeMirror in order to have the intended effects.
I've been able to use the latest CLJSJS version of CodeMirror but it doesn't pass my unit tests whereas the most recent non-CLJSJS version directly from CodeMirror does pass. So I'm guessing I need the latest CodeMirror, which isn't yet offered via CLJSJS yet.
Here's part of my build.boot file:
(deftask testing []
(set-env! :source-paths #(conj % "test/cljs"))
identity)
(deftask test []
(comp (testing)
(test-cljs :js-env :phantom
:exit? true)))
(deftask auto-test []
(comp (testing)
(watch)
(test-cljs :js-env :phantom)))

Why does sbt give "object swing is not a member of package scala" for import scala.swing?

Sbt version: 0.13.8
Scala version: 2.11.2
When compiling my scala swing application with scalac, it simply compiles.
However, when compiling the same files with SBT, it provides the following error:
[error] my/file/path.scala:1: object swing is not a member of package scala
[error] import scala.swing._
I added the scala version to my build.sbt. I even configured scalaHome (which I believe should never be in a build.sbt).
The lines in build.sbt:
scalaVersion := "2.11.2"
scalaHome := Some(file("/my/scala/location/opt/scala-2.11.2/"))
The
/my/scala/location/opt/scala-2.11.2/lib
directory contains the sacla swing lib: scala-swing_2.11-1.0.1.jar , this is also why scalac simply compiles.
Some might say I should add swing to my libraryDependencies in the build.sbt, however it shouldn't, since it is part of the core library and scalaHome is configured.
How to get sbt to notice the swing core library in a natural manner?
Bonus question:
How to configure scalaHome outside of build.sbt (without hacking the sbt jar itself) or better, have it notice the SCALA_HOME environment variable?
As of 2.11, the scala swing package is no longer listed among scala's standard library api and in fact is described in its own README as "mostly unsupported".
I think you should expect to have to include it as a dependency.
See also What's wrong with my scala.swing?