Skip to content

Instantly share code, notes, and snippets.

@andrewhodel
Last active September 7, 2024 03:29
Show Gist options
  • Save andrewhodel/780f21c748cc570d96bd92e2655d9e39 to your computer and use it in GitHub Desktop.
Save andrewhodel/780f21c748cc570d96bd92e2655d9e39 to your computer and use it in GitHub Desktop.
nodejs modules

ECMAScript modules sometimes known as ES modules

These use the module loader system in the Browser.

When a module is loaded, it has a special name that is only available within this module loader system. The special name is why import doesn't work with modules that import other modules using that special name, because import() cannot assign that name.

Loading is possible with:

  1. import is capable of loading the module's script and setting the special name of the module. This allows other modules to access it. It is not capable of load or error events or a retry function or subresource integrity.
  2. import() is capable of a Promise but it does not allow access to the special name of the module and does not have subresource integrity.
  3. importmap is capable of loading module scripts, setting the special names and subresource integrity. It is not capable of load or error events or a retry function.

You can load a module script with import() with certainty, then access it but other modules that look for it's special name must be rewritten to access it using the global namespace. Modules loaded dynamically with import() cannot set a special name. However, there is a Promise that allows retrying with error handling.

Using import and setting the special name: import { * as specialname } from "./modules/specialname.js"; then other modules can import the special name. However, there are no load or error events or a retry function.

// this module could use module system special names to access other modules
import { func1 } from specialname1;

func1 = function() {

	var o = {data_to_keep: 'asdf'};

	// return the object
	return o;

}

export {func1};

CommonJS modules only work in Node.JS

These use module.exports.

module.exports = class AClass {

	constructor() {
		// ran on init
		this.data_to_keep = 'asdf';
	}

}

raw classes in the global scope

Raw classes are the easiest and work in the browser.

It's simply a class in the global scope.

It is easy to load into a script element that has a load event and can be retried by using an XHR request and Blob.URL.

The script element can easily implement subresource integrity.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

class Rectangle {
  constructor(height, width) {
    // ran on init
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
  
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield
  // (uses .next() as an iterator)
  *getSides() {
    yield this.height;
    yield this.width;
    yield this.height;
    yield this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]
@andrewhodel
Copy link
Author

andrewhodel commented Sep 7, 2024

A explanation of the problem with ECMAScript/ES modules.

mrdoob/three.js#29346

importmap could add support for load events as it already supports subresource integrity.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

Regardless:

  1. importmap should work with events and have a retry function that can be invoked. (https://issues.chromium.org/issues/365076686)
  2. import() should have subresource integrity (https://issues.chromium.org/issues/365076679) and already has a Promise.
  3. modules such as OrbitControls.js should be able to access window.THREE instead of accessing a module name that is only in the module system. (mrdoob/three.js#29346 (comment))

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