JSPM & third party library shims

1804632 I was hitting a LOT of friction trying to get unregistered third-party packages to work with JSPM. "Frictionless browser package management" is the tag line, but only if you remain in the "jspm universe".

In other words, if you try using a package that is not in the jspm registry, you're going to eventually run into vague dependency related issues.

The example

Let's suppose there's a JavaScript library you want to use that's not in the jspm registry. Let's take https://github.com/corinis/jsForm for example. jsForm is a jQuery plugin that's dependent on jQuery, but not registered or part of the jspm universe. You can manually install jsForm from JSPM via "jspm install github:cornis/jsForm" and jspm will be happy to do your bidding.

Unfortunately, if you try importing jsForm in a ES6 module like this:

Code Snippet
  1. import "corinis/jsForm";
  3. @autoinject
  4. export class Login {
  5.     private auth:AuthManager;
  6.     router:Router;
  7.     providers: any[];
  9.     email:string;

You might run the risk of having jsFrom loading in an incorrect order (where jsForm loads first, before jQuery is loaded). In order to overcome this problem you have two choices:

1. Manual Import

This step means modifying your initial SystemJS import statement like this:

Code Snippet
  1. <script type="text/javascript">
  3.     System.import("jquery").then(function() {
  4.         System.import("aurelia-bootstrapper");
  5.     });
  7. </script>

This ensures jQuery is loaded before everything else. This method feels like a hack and probably wont scale if we run into more dependency related issues. So looking for a better way .... we find

2. The 'proper' Shim Method

The proper way is to use a shim. Basically, what we have to do is write an override (aka shim) that "explicitly" defines the dependencies for our non-registered jsForm jspm package. We do that by writing something similar to:

Code Snippet
  1. {
  2.    registry: 'jspm',
  3.    main: 'js/jquery.jsForm',
  4.    shim: {
  5.     'js/jquery.jsForm': {
  6.         deps: ['jquery']
  7.      }
  8.    },
  9.    dependencies: { jquery: '*' }
  10. }

And we'll need to smash all this into a single line like so:

jspm install github:corinis/jsForm -o "{ registry: 'jspm', main: 'js/jquery.jsForm', shim: { 'js/jquery.jsForm': { deps: ['jquery'] } }, dependencies: { jquery: '*' } }"

Ugh. Yes, ugly. This is the friction I'm talking about. It's not very friendly.

A little bit about the override schema:

main - path to the main JS file in your library to load. In our case "jspm_pacakges\github\corinis\[email protected]\js\jquery.jsForm.js". Notice this is a relative path from the extracted package (in bold).

shim: { 'js/jquery.jsForm' : { deps:['jquery'] } } - our dependency, notice here we're using the aliased name to "jquery" as defined in our config.js file.

dependencies: - any version of jquery will do.

registry: - wont work without it.

Now, if you execute the above JSPM command with the shim override, you'll see config.js configuration changed and additional dependency listed for jsForm:

Code Snippet
  1. "github:corinis/[email protected]": {
  2.       "jquery": "github:components/[email protected]"
  3.     },

Happy days. :)

Brian Chavez