Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

SystemJS

Build StatusGitterBackers on Open CollectiveSponsors on Open Collective

Configurable module loader, running System modules at almost-native speed, and enabling ES module semantics and features such as top-level await, dynamic import, and import maps with full compatibility in older browsers including IE.

Release Links:

For discussion, join the Gitter Room.

Examples

The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.

Performance

SystemJS is designed for production modules performance and can load multiple modules in less than a millisecond. Its performance is only around a factor of 1.5 times the performance of native ES modules, as seen in the following performance benchmark, which was run by loading 426 javascript modules (all of @babel/core) on a Macbook pro with fast wifi internet connection. Each test was the average of five page loads in Chrome 80.

ToolUncachedCached
Native modules1668ms49ms
SystemJS2334ms81ms
es-module-shims2671ms602ms

ES module Shims, like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers. The performance difference is because source rewriting happens in browser instead of ahead-of-time like SystemJS handles via the System module format.

Overview

Introduction video

SystemJS provides two hookable base builds:

1. s.js minimal loader

The minimal 2.3KB s.js loader provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don't support native modules, including IE11++.

Since the ES module semantics such as live bindings, circular references, contextual metadata, dynamic import and top-level await can all be fully supported this way, while supporting CSP and cross-origin support, this workflow can be relied upon as a polyfill-like path.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Loads and resolves modules as URLs, throwing for bare specifier names (eg import 'lodash') like the native module loader.
  • Loads System.register modules.
  • Core hookable extensible loader supporting custom extensions.

2. system.js loader

The 3.7KB system.js loader loader builds on the s.js core and adds support for global loading, non-javascript module, and the SystemJS registry API.

  • Support for loading bare specifier names through import maps (formerly package maps, formerly map configuration), loaded via <script type="systemjs-importmap"> (requires a fetch polyfill for eg IE11).
  • Includes the global loading extra for loading global scripts, useful for loading library dependencies traditionally loaded with script tags.
  • Tracing hooks and registry deletion API for reloading workflows.
  • Supports loading Wasm, CSS and JSON module types.

3. system-node.cjs loader

The system-node.cjs loader is a version of SystemJS build designed to run in Node.js, typically for workflows where System modules need to be executed on the server like SSR. It has the following features:

  • Loading System modules from disk (via file:// urls).
  • Loading System modules from network (via http:// urls), with included caching that respects the Content-Type header.
  • Loading global modules with the included global loading extra
  • Supports loading Wasm, CSS and JSON module types.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.

Loading CommonJS modules is not currently supported in this loader and likely won't be. If you find you need them it is more advisable to use Node.js native module support where possible instead of the SystemJS Node.js loader.

Extras

The following pluggable extras can be dropped in with either the s.js or system.js loader:

  • AMD loading support (through Window.define which is created).
  • Named exports convenience extension support for global and AMD module formats (import { x } from './global.js' instead of import G from './global.js'; G.x)
  • Named register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Transform loader support, using fetch and eval, supporting a hookable loader.transform

The following extras are included in system.js loader by default, and can be added to the s.js loader for a smaller tailored footprint:

  • Global loading support for loading global scripts and detecting the defined global as the default export. Useful for loading common library scripts from CDN like System.import('//unpkg.com/lodash').
  • Module Types.css, .wasm, .jsonmodule type loading support in line with the existing modules specifications.

Since all loader features are hookable, custom extensions can be easily made following the same approach as the bundled extras. See the hooks documentation for more information.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Installation

npm install systemjs

Documentation

Example Usage

Loading a System.register module

You can load System.register modules with a script element in your HTML:

<scriptsrc="system.js"></script><script>System.import('/js/main.js')</script><script>System.import('name-of-module')</script>

Loading with System.import

You can also dynamically load modules at any time with System.import():

System.import('/js/main.js');

where main.js is a module available in the System.register module format.

Bundling workflow

For an example of a bundling workflow, see the Rollup Code Splitting starter project - https://github.com/rollup/rollup-starter-code-splitting.

Note that when building System modules you typically want to ensure anonymous System.register statements like:

System.register([],function(){ ... });

are emitted, as these can be loaded in a way that behaves the same as normal ES modules, and not named register statements like:

System.register('name',[],function(){ ... });

While these can be supported with the named register extension, this approach is typically not recommended for modern modules workflows.

Import Maps

Say main.js depends on loading 'lodash', then we can define an import map:

<scriptsrc="system.js"></script><scripttype="systemjs-importmap">{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}}</script><!-- Alternatively:<script type="systemjs-importmap" src="path/to/map.json">--><script>System.import('/js/main.js');</script>

Community Projects

A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.

  • es-dev-server - A web server for developing without a build step.
  • import map overrides - Dynamically inject an import map stored in local storage so that you can override the URL for any module. Can be useful for running development modules on localhost against the server.
  • js-env - Collection of development tools providing a unified workflow to write JavaScript for the web, node.js or both at the same time.
  • jspm.org - Package manager for native modules, using SystemJS for backwards compatibility.
  • single-spa - JavaScript framework for front-end microservices.
  • systemjs-webpack-interop - npm lib for setting webpack public path and creating webpack configs that work well with SystemJS.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.

Loader Extensions

This list can be extended to include third-party loader extensions. Post a PR.

Compatibility with Webpack

Code-splitting builds on top of native ES modules, like Rollup offers, are an alternative to the Webpack-style chunking approach - offering a way to utilize the native module loader for loading shared and dynamic chunks instead of using a custom registry and loader as Webpack bundles include. Scope-level optimizations can be performed on ES modules when they are combined, while ensuring no duplicate code is loaded through dynamic loading and code-sharing in the module registry, using the features of the native module loader and its dynamic runtime nature.

systemjs-webpack-interop is a community-maintained npm library that might help you get webpack and systemjs working well together.

As of webpack@4.30.0, it is now possible to compile webpack bundles to System.register format, by modifying your webpack config:

{output: {libraryTarget: 'system',}}

If building code using the System global in Webpack, the following config is needed to avoid rewriting:

{module: {rules: [{parser: {system: false}}]}}

Using npm packages

Third party libraries and npm packages may be used as long as they are published in a supported module format. For packages that do not exist in a supported module format, here is a list of github repos that publish System.register versions of popular third party libraries (such as react, react-dom, rxjs, etc).

Polyfills for Older Browsers

Promises

Both builds of SystemJS need Promises in the environment to work, which aren't supported in older browsers like IE11.

Promises can be conditionally polyfilled using, for example, Bluebird (generally the fastest Promise polyfill):

<script>if(typeofPromise==='undefined')document.write('<script src="node_modules/bluebird/js/browser/bluebird.core.js"><\/script>');</script>

Generally document.write is not recommended when writing web applications, but for this use case it works really well and will only apply in older browsers anyway.

Fetch

To support import maps in the system.js build, a fetch polyfill is need. The GitHub polyfill is recommended:

<script>if(typeoffetch==='undefined')document.write('<script src="node_modules/whatwg-fetch/fetch.js"><\/script>');</script>

Constructable Stylesheets

If using CSS modules, a Constructable Stylesheets polyfill is needed - see the module types documentation for further info.

Contributing to SystemJS

Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.

To run the tests:

npm run build && npm run test

Changes

For the changelog, see CHANGELOG.md.

License

MIT

About

Dynamic ES module loader

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages