Search code examples
ecmascript-6polymer-1.0web-componentsystemjsjspm

Loading multi versioned Web Component dependencies with SystemJS / JSPM?


Just a disclaimer - this is a hypothetical scenario as I'm trying to figure out the best way to handle web component direct and transitive dependencies using something like JSPM and SystemJS.

Scenario 1

Suppose I have 2 web components - component-a and component-b. One is built with [email protected] and another is built with [email protected].

Each component author listed Polymer as a peer dependency and momentjs as a direct dependency in their package.json file like this:

  "dependencies": {
    "moment.js": ">= 1.0.1 <= 1.8.0"
  }   
  "peerDependencies": {
    "Polymer.js": "0.5.0^",
  }   

So in this case when the developer declares the package.json dependencies on both of these components the package manager could figure out the best version of moment.js to install and make it available. Lets assume that's version 1.8.0.

Great - just one version of moment.js to deal with for both components. Now how do the components load / inject the dependency? Does JSPM and SystemJS currently have the ability to support this?

For example in this article Taming Polymer with SystemJS and Typescript the author performs imports that delegate to SystemJS like this:

 import 'elements/app-frontend';

So I suppose momentjs would follow a similar approach and import like this (Within the typescript files of component-a and component-b:

 import 'js/momentjs';

In the above case the momentjs dependency does not know what version will be fetched since the import declaration is unaware of the version (since it written at design time).

Later on when the component is used in and component is used in an application JSPM figures out the best for the momentjs depedency to install.

In this case lets assume that it install it in a layout like this:

`jspm_packages/momentjs/[email protected]`

So how does JSPM become aware the import statement import 'js/momentjs' translates to the import of jspm_packages/momentjs/[email protected]?

In this case it's fairly trivial, but it get more tricky in scenario 2 below ... I think.

Scenario 2

Same as scenario one except the version requirements on momentjs are mutually exclusive. For example component-a requires version 1.2.4 and component-b requires version 2.4.4.

So both components perform the import like this:

 import 'js/momentjs';

But jspm_packages installs both versions like this:

`jspm_packages/momentjs/[email protected]`
`jspm_packages/momentjs/[email protected]`

So now how does SystemJS know to that component-a needs version 1.4.4 and component-b needs version 2.4.4?

To summarize: 1) Is JSPM ok with having multiple versions of the same dependency?

According to this article Introduction to the Jspm package manager and the SystemJs module loader and an answer from guybeford it does, but how then does each component get the right version?

2) Does SystemJS / JSPM have a way of configuring version meta data for each component?

3) Does SystemJS have a way of understanding and injecting the right version of a dependency into the web component?

TIA, Ole


Solution

  • Also what happens if the component requires several other modules, like CSS etc?

    I'm not sure what you mean. You can import multiple modules and other contents (likely via plugins) usting SystemJS.

    1) Is JSPM ok with having multiple versions of the same dependency?

    I think you partially answered this question. JSPM will always select and install only one version for each component, which best matches the requirements from other components. If there is a conflict, JSPM will ask to choose manually.

    So how does JSPM become aware the import statement import 'js/momentjs' translates to the import of jspm_packages/momentjs/[email protected]?

    The config.js file assigns import names (not sure the nomenclature) for installed packages. It is actually possible to change those names using jspm install x=npm:package syntax. This will result in config like

    "x": "npm:[email protected]"
    

    You can then both import x and import npm:[email protected].

    2) Does SystemJS / JSPM have a way of configuring version meta data for each component?

    I think that the structure of config.js has all you need. It contains dependencies with their versions.

    "component-a": {
      "momentjs": "[email protected]"
    },
    "component-b": {
      "momentjs": "[email protected]"
    }
    

    3) Does SystemJS have a way of understanding and injecting the right version of a dependency into the web component?

    I would expect SystemJS to use this information to import the correct version when either component-a or component-b is requested.

    I am not sure though how to have JSPM install packages this way, retaining multiple versions of a package. I think it deserves a separate, specialized question.