Editor - ES modules

Last modified:

Introduction

All scripts (inline and default) in Blockstudio load with type="module" applied to them by default. This means that it is possible to make use of the import syntax for your blocks' scripts.

Arrow Forward Circle

For a more in-depth look into ES modules, visit the mdn web docs.

Let's imagine the following code inside a script.js:

script.js

                import { LitElement, css, html } from 'https://esm.sh/lit@2.5.0';

    export class CallToAction extends LitElement {
      static properties = {
        name: {},
      };

      static styles = css`
        :host {
          color: red;
        }
      `;

      constructor() {
        super();
        this.product = 'Blockstudio';
      }

      render() {
        return html`<p>Buy ${this.product}!</p>`;
      }
    }
    customElements.define('call-to-action', CallToAction);

        
Copy

The example above would create a web component using Lit , importing all necessary components and functions from an ESM compatible CDN, in this case esm.sh. While there is nothing wrong with this approach, it has the disadvantage of needing to request the necessary assets from an external site, risking broken scripts if the CDN is down.

Blockstudio includes a handy way to download ES Modules to the block, eliminating the need for external ESM CDNs during production. Please note that this is only working if you enabled esbuild in the editor options.

Setup

To download a module to your block directory, simply swap the CDN url.

script.js

                import { LitElement, css, html } from 'blockstudio/lit@2.5.0';

        
Copy

When inside the editor, the CDN url will still be used (Blockstudio is using esm.sh) when previewing and working on the block. However, upon saving the block, Blockstudio will download a copy of the requested module file and save it to the directory of the current block.

Folder Open

cta

Folder Open
_dist
Logo Nodejs
script-1666269686.js
Folder Open
modules
Folder Open
lit
Logo Nodejs
2.5.0.js
Document
block.json
Document
index.php
Logo Nodejs
script.js

The script file will be rewritten on save to accustom for the locally hosted module, in the example above, the generated script would have the following import:

script.js

                import { LitElement, css, html } from './modules/lit/2.5.0.js';

        
Copy

There you go! The world of NPM at your fingertips without the boring boilerplate of setting up bundlers and other tools. If you are concerned about performance due to not having a single JS bundle, this article is worth a read.

Caveats

There are a couple of things to consider when working with ES modules inside the editor.

Version

Normally, modules can be used from CDNs without the version number. In this case the newest version will always be used. Since Blockstudio is not saving any information into the database, a version number is required when using modules.

Same modules

Modules are scoped to their blocks. Even if you use the same module with the same version number across multiple blocks, Blockstudio will still download the requested module to the block. This is mainly because blocks should be self-contained units that can easily be shared across other installs or sites.

On top of that, the same module will be requested twice if both blocks are present on a page. This is not so much of an issue if the block is loading a very specific module like a slider library. However, if you are creating multiple blocks that rely on the same framework like above (Lit), loading the same module multiple times can become a performance issue.

This problem can be solved by using the script-inline.js instead of the script.js file. Blockstudio will rewrite each of the imports to point to the location of the first occurrence of the module if the name and version number are the same.