Skip to content

Instantly share code, notes, and snippets.

@digitalsadhu
Last active August 7, 2019 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digitalsadhu/0a0b29ca43202686a3bfbeee3797515e to your computer and use it in GitHub Desktop.
Save digitalsadhu/0a0b29ca43202686a3bfbeee3797515e to your computer and use it in GitHub Desktop.

The following lays out roughly, a proposed way to sharing dependencies across podlets.

The idea is that, through a cli tool, it will be possible to manage which libraries are available across the organisation. Here we are using react (and react-dom) as a global cross podlet dependency to illustrate the proposed workflow.

First, we publish a global version of react at a specific version. The cli tool, downloads react, converts it to esm and uploads it to the CDN at a convention based URL.

asset-pipe global publish --org finn react@16.8.6

This results in the file being available at the following URL:

https://asset-pipe-v3.storage.googleapis.com/finn/pkg/react/16.8.6/index.js

React dom is also needed for react and it has a peer dependency on react so we need to replace bare references to react (within react-dom) with the version we published in the previous step. We can do this using the --global flag to tell the global publish command to replace any imports of the form import React from 'react' with import React from <cdn url>

asset-pipe global publish --org finn --global react@16.8.6 react-dom@16.8.6

This results in react-dom being available at the URL:

https://asset-pipe-v3.storage.googleapis.com/finn/pkg/react-dom/16.8.6/index.js

and this file contains an import reference to react on the CDN which looks like:

import React from 'https://asset-pipe-v3.storage.googleapis.com/finn/pkg/react/16.8.6/index.js';

We then create an alias for react@16.8.6. Alias are needed to make it easier to keep global depenencies in sync. If all podlets need to depend on exact versions of react then its very easy for them to get of sync. 1 podlet might depend on react@16.8.0 which another might depend on 16.8.6 etc. By using aliases (or tags) we can have all podlets depend on a major version of the module as in react v16 and they will all be getting the same version of react.

The following command sets an alias v16 to point to react version 16.8.6:

asset-pipe global alias --org finn react@16.8.6 v16

This will result in the following URL:

https://asset-pipe-v3.storage.googleapis.com/finn/alias/react/v16/index.js

We then do the same for react-dom:

asset-pipe global alias --org finn react-dom@16.8.6 v16

And finally we need to add entries in the global import-map for react and react-dom:

asset-pipe global import-map react react@v16
asset-pipe global import-map react-dom react-dom@v16

Which results in an import map file:

https://asset-pipe-v3.storage.googleapis.com/finn/import-map.json

with the contents:

{
    "imports": {
        "react": "https://asset-pipe-v3.storage.googleapis.com/finn/pkg/react/v16/index.js",
        "react-dom": "https://asset-pipe-v3.storage.googleapis.com/finn/pkg/react-dom/v16/index.js"
    }
}

Doing this enables us to manage shared dependencies org wide such that they can be used in the asset publish process in each podlet. Each podlet can run its own publish command and make use of this import-map file to replace bare imports with the correct CDN URL and we can manage this file org wide.

@trygve-lie
Copy link

As long as React does not publish ES modules I think this is a sane, though not perfect, solution. We should though approach a couple of other libraries to see if we can do the same approach.

Another interesting example I would like to examine is lit-element. lit-element are ES modules but as I understand it, lit-element is only published to npm and there is no official bundle of lit-element published as is. One aspect with lit-element is that is has a dependency on lit-html which also can be used as a standalone module.

It would be nice to be able to upload a bundle of lit-element where lit-html is decoupled in the same way we do with react and react-dom.

@digitalsadhu
Copy link
Author

Ran a publish and tested the following:

import {
    LitElement,
    html,
} from 'https://asset-pipe-v3.storage.googleapis.com/finn/pkg/lit-element/2.2.1/index.js';

class SimpleGreeting extends LitElement {
    static get properties() {
        return { name: { type: String } };
    }

    constructor() {
        super();
        this.name = 'World';
    }

    render() {
        return html`
            <p>Hello, ${this.name}!</p>
        `;
    }
}

customElements.define('simple-greeting', SimpleGreeting);
<simple-greeting name="Everyone"></simple-greeting>

Worked as expected!

@trygve-lie
Copy link

Niceness

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment