Official Support for RequireJS in WebJars

WebJars Locator now has direct support for RequireJS! For a while the WebJars Play helper library has had support for RequireJS which was great but it had a few issues and wasn’t useful outside of Play.

There is now a org.webjars.RequireJS.getSetupJavaScript(String webjarUrlPrefix) method that produces the RequireJS configuration for the WebJars you are using. If you are using only the jQuery WebJar then that JavaScript configuration looks like:

var webjars = {
    versions: { 'requirejs': '2.1.10', 'jquery': '2.1.0' },
    path: function(webjarid, path) {
        return '/webjars/' + webjarid + '/' + webjars.versions[webjarid] + '/' + path;
    }
};
 
var require = {
    callback: function() {
        // no-op webjars requirejs plugin loader for backwards compatibility
        define('webjars', function () {
            return { load: function (name, req, onload, config) { onload(); } }
        });
 
        // all of the webjar configs from their webjars-requirejs.js files
 
        // webjar config for jquery
        requirejs.config({
            paths: { "jquery": webjars.path("jquery", "jquery") },
            shim: { "jquery": { "exports": "$" } }
        });
    }
}

This sets up the paths for RequireJS modules in WebJars and pulls in any other custom configuration from the WebJar’s RequireJS config. To use this setup JavaScript with RequireJS you can add something like the following to your web page:

<script>
// the following includes the setup JavaScript directly in the page
// (in this case using Play's server-side templating)
@Html(org.webjars.RequireJS.getSetupJavaScript("/webjars/"))
 
// alternatively you can create a controller that returns the JavaScript
// and then use a src="blah" to load the setup JavaScript
</script>
 
<!-- The following can use the WebJars Locator to avoid hard-coding the full path -->
<script data-main="/assets/index" src="/webjars/requirejs/2.1.10/require.min.js"></script>

The WebJars Play library now has a new helper that wraps all that up into a nice function:

@Html(org.webjars.play.RequireJS.setup("index"))

That loads the setup JavaScript and loads RequireJS with the right data-main. Check out a full example of this with AngularJS in the Play Angular Seed Activator template.

Now using RequireJS is just normal syntax (no more webjars! prefix), like:

require(["jquery"], function(jquery) {
    console.log(jquery)
});

All of this was added very recently so make sure you are using at least webjars-locator version 0.12 and webjars-play version 2.2.1-2. Also this change may cause some incompatibilities in the WebJar RequireJS config files (webjars-requirejs.js) so if you experience strange behavior please file an issue on the WebJar.

Let me know how it goes!

  • Patrick

    This is very cool! I’ve taken the liberty of submitting a couple of PRs to update the webjars I need to use with this new approach. I take it similar changes will need to be made to all webjars in order to use this? Or perhaps I’m missing something.

    • Yeah, you are right that we need to eventually get all the WebJars updated to this convention. Thanks for the PRs!

  • Nepomuk Seiler

    Hi James,

    Great stuff! Can you provide a minimal play application which demonstrates the new features? That would be awesome :)

    cheers,
    Muki

  • Pingback: RequireJS Optimization with Play 2.2, WebJars, and CDNs - Marius Soutier NoDev - Not Only Software Development()

  • Roy

    Correct me if I’m wrong, but would it be a good idea to allow the paramter webjarUrlPrefix to be optional, and henceforth data-main to be optional as well?

    • Roy

      Whoops, I meant the parameter in RequireJS.setup()

      • Outputting the correct paths requires the prefix so unfortunately it can’t be optional.

  • Simeon Fitch

    If one is using a pre-0.12 webjar-locator artifact, what is the recommended way to get the new RequireJS support to find it? For example, I’m getting this when attempting to use visjs 0.7.4:

    `org.webjars.RequireJS – Could not read WebJar RequireJS config for: visjs 0.7.4`

    • Can you upgrade webjars-locator to a newer version? I think that is the easiest way.

      • Simeon Fitch

        Are you suggesting I used a SNAPSHOT version? From my seat 0.17 is the latest version:

        https://github.com/webjars/webjars-locator/releases

        I see my original question was confusing. I meant to ask about how one should best use other WebJars that *don’t* yet have the RequireJS metadata in their bundled pom.xml files.

        • Ah… I meant use 0.17 but sounds like that isn’t what you need. For WebJars that don’t have RequireJS config please file an issue on the WebJar. As a workaround you can inject your own RequireJS config (which I haven’t really documented anywhere but need to). Basically you’ll need to add some JavaScript somewhere that adds the config manually. Can you also file an issue on https://github.com/webjars/webjars to get this documented?

          • Simeon Fitch

            Done. One last question on this: should the requirejs WebJar be explicitly included as well? I have `”org.webjars” % “requirejs” % “2.1.14-1″` in my `build.sbt` file, but get a `Could not read WebJar RequireJS config for: requirejs 2.1.14` warning from the locator.

            Very excited about this framework. I hope it takes off. Makes things vastly more manageable, especially for us non-JS pros coming from the Scala side where artifact management is common practice.

          • Thanks! I just released requirejs 2.1.14-2 which has an empty requirejs config to avoid this warning. Let me know if that removes the error. Note: The sync to Maven Central will take a few hours.

  • Nader Hadji Ghanbari

    Great stuff James! By the way what about non-single-page apps (when there is no entry point). Is removing the `data-main` part enough?

    • That `data-main` is what tells RequireJS which file to load to start the app. So you could drop that part but then no app will be loaded.

      • Nader Hadji Ghanbari

        Thanks. I tried it. Facing some problems with those WebJars without a `requirejs` shim. Will try to add shims to them and make some pull requests if successful.