Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript Module shim for UMD bundles #127

Open
justinfagnani opened this issue Dec 6, 2017 · 1 comment
Open

JavaScript Module shim for UMD bundles #127

justinfagnani opened this issue Dec 6, 2017 · 1 comment

Comments

@justinfagnani
Copy link

UMD isn't currently compatible with JavaScript modules because import and export declarations would cause a syntax errors in engines that don't yet support modules. This makes UMD now less universal than it could be.

#125 makes UMD bundles loadable via import statements, but the bundle will still write to globals (or use define or exports if available), so there are no useful symbols to import.

I think we can make importing UMD from JS modules better with a small shim that's imported instead and provides real exports.

There are two possible versions of the shim:

  1. A generic shim that exports a single object with all the UMD exports.
  2. A custom shim with a JS export for every UMD export

Generic Shim

The shim first sets up a global object to capture the UMD exports, then loads the UMD, then resets the global:

my-module-setup.js:

// Each UMD-JS-module shim needs it's _own_ setup module, even though the contents are the same, so that it evaluates before each UMD loads
window.exports = {}

my-module.js:

// We need a separate import to run code before the UMD module evaluates
import './my-module-setup.js';

// load the UMD module, which will populate window.exports
import './my-module.umd.js';

//export the UMD exports
export default let exports = window.exports;

// cleanup
window.exports = undefined;

Custom Shim

The custom shim works the same, but uses individual exports. This would likely be generated:

my-module.js:

// We need a separate import to run code before the UMD module evaluates
import './my-module-setup.js';

// load the UMD module, which will populate window.exports
import './my-module.umd.js';

//export the UMD exports
export const a = window.exports.a;
export const b = window.exports.b;

// cleanup
window.exports = undefined;

Custom shims would not support mutable bindings, ie you can't reassign an export from within the defining module.

@SimonHeimberg
Copy link

SimonHeimberg commented Jun 15, 2022

Why not having window.exports = {} in the shim instead of import './my-module-setup.js'?

The shim depends on the UMD template:

  • commonStrict.js (and commonStrictGlobal.js) uses exports
  • returnExports.js (and returnExportsGlobal.js) uses module.exports
  • amdWeb.js (and amdWebGlobal.js) uses only define()

In case the module has dependencies, require() must be provided in the shim as well.

🤔 For own modules maybe writing them as es6 (with import and export statements) and converting to UMD is simpler (or using esm for nodejs). But for 3rd party libraries, shims could still be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants