Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
SystemJS is a dynamic module loader that can load ES modules, AMD, CommonJS, and global scripts in the browser and Node.js. It provides a way to load modules asynchronously and supports various module formats, making it a versatile tool for managing dependencies and module loading in JavaScript applications.
Loading ES Modules
SystemJS can dynamically import ES modules. The code sample demonstrates how to load an ES module asynchronously and handle the loaded module.
System.import('/path/to/module.js').then(function(module) {
console.log(module);
});
Loading CommonJS Modules
SystemJS can also load CommonJS modules. The code sample shows how to load a CommonJS module asynchronously.
System.import('/path/to/commonjs-module.js').then(function(module) {
console.log(module);
});
Loading AMD Modules
SystemJS supports loading AMD modules. The code sample demonstrates how to load an AMD module asynchronously.
System.import('/path/to/amd-module.js').then(function(module) {
console.log(module);
});
Loading Global Scripts
SystemJS can load global scripts that do not export any modules. The code sample shows how to load a global script asynchronously.
System.import('/path/to/global-script.js').then(function() {
console.log('Global script loaded');
});
Configuring SystemJS
SystemJS allows configuration for module loading. The code sample demonstrates how to configure the base URL, paths, and module mappings.
System.config({
baseURL: '/base/url',
paths: {
'npm:': 'https://unpkg.com/'
},
map: {
'jquery': 'npm:jquery@3.5.1/dist/jquery.js'
}
});
RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, such as Rhino and Node. Compared to SystemJS, RequireJS primarily focuses on AMD modules and does not support as many module formats.
Webpack is a module bundler that takes modules with dependencies and generates static assets representing those modules. Unlike SystemJS, which is a dynamic module loader, Webpack bundles modules at build time, which can result in better performance for production applications.
Browserify allows you to use Node.js-style require() to organize your browser code and load modules. It transforms Node.js modules into a format that can be used in the browser. Compared to SystemJS, Browserify focuses on CommonJS modules and does not support as many module formats.
ES Module Loader is a polyfill for the ES Module Loader specification. It provides a way to load ES modules in environments that do not natively support them. Compared to SystemJS, ES Module Loader is more focused on ES modules and does not support other module formats.
SystemJS is a hookable, standards-based module loader. It 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, running almost-native module speeds while supporting top-level await, dynamic import, circular references and live bindings, import.meta.url, module types, import maps, integrity and Content Security Policy with compatibility in older browsers back to IE11.
Support SystemJS by becoming a sponsor. Your logo will show up here with a link to your website.
Thank you to all our backers! 🙏 [Become a backer]
The minimal 2.8KB s.js production loader includes the following features:
System.register
modules, the CSP-compatible SystemJS module format.<script type="systemjs-importmap">
.The 4.2KB system.js loader adds the following features in addition to the s.js
features above:
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:
file://
urls) or the network, with included caching that respects the Content-Type header.applyImportMap
api).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.
The following pluggable extras can be dropped in with either the s.js or system.js loader:
Window.define
which is created).System.register('name', ...)
named bundles which can then be imported as System.import('name')
(as well as AMD named define support)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:
System.import('//unpkg.com/lodash')
..css
, .wasm
, .json
module 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.
To support easy loading of TypeScript or ES modules in development SystemJS workflows, see the SystemJS Babel Extension.
SystemJS does not support direct integration with the native ES module browser loader because there is no way to share dependencies between the module systems. For extending the functionality of the native module loader in browsers, see ES module Shims, which like SystemJS, provides workflows for import maps and other modules features, but on top of base-level modules support in browsers, which it does using a fast Wasm-based source rewriting to remap module specifiers.
SystemJS is designed for production modules performance roughly only around a factor of 1.5 times the speed 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.
Tool | Uncached | Cached |
---|---|---|
Native modules | 1668ms | 49ms |
SystemJS | 2334ms | 81ms |
The systemjs-examples repo contains a variety of examples demonstrating how to use SystemJS.
npm install systemjs
You can load System.register modules with a script element in your HTML:
<script src="system.js"></script>
<script type="systemjs-module" src="/js/main.js"></script>
<script type="systemjs-module" src="import:name-of-module"></script>
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.
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.
Say main.js
depends on loading 'lodash'
, then we can define an import map:
<script src="system.js"></script>
<script type="systemjs-importmap">
{
"imports": {
"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"
}
}
</script>
<!-- Alternatively:
<script type="systemjs-importmap" src="path/to/map.json" crossorigin="anonymous"></script>
-->
<script type="systemjs-module" src="/js/main.js"></script>
IE11 continues to be fully supported, provided the relevant polyfills are available.
The main required polyfill is a Promise
polyfill. If using import maps a fetch
polyfill is also needed.
Both of these can be loaded conditionally using for example using Bluebird Promises and the GitHub Fetch Polyfill over Unpkg:
<script>
if (typeof Promise === 'undefined')
document.write('<script src="https://unpkg.com/bluebird@3.7.2/js/browser/bluebird.core.min.js"><\/script>');
if (typeof fetch === 'undefined')
document.write('<script src="https://unpkg.com/whatwg-fetch@3.4.1/dist/fetch.umd.js"><\/script>');
</script>
located before the SystemJS script itself. The above will ensure these polyfills are only fetched for older browsers without Promise
and fetch
support.
When using external import maps (those with src=""
attributes), there is an IE11-specific workaround that might need to be used. Browsers should not make a network request when they see <script type="systemjs-importmap" src="/importmap.json"></script>
during parsing of the initial HTML page. However, IE11 does so. Codesandbox demonstration
Normally this is not an issue, as SystemJS will make an additional request via fetch/xhr for the import map. However, a problem can occur when the file is cached after the first request, since the first request caused by IE11 does not send the Origin request header by default. If the request requires CORS, the lack of an Origin request header causes many web servers (including AWS Cloudfront) to omit the response CORS headers. This can result in the resource being cached without CORS headers, which causes the later SystemJS fetch() to fail because of CORS checks.
This can be worked around by adding crossorigin="anonymous"
as an attribute to the <script type="systemjs-importmap">
script.
A list of projects that use or work with SystemJS in providing modular browser workflows. Post a PR.
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 using webpack@<5, the following config is needed to avoid rewriting references to the global System
variable:
{
module: {
rules: [
{ parser: { system: false } }
]
}
}
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).
Project bug fixes and changes are welcome for discussion, provided the project footprint remains minimal.
Task running is handled by Chomp (https://chompbuild.com).
To run the tests:
npm install -g chomp
chomp test
For the changelog, see CHANGELOG.md.
MIT
FAQs
Dynamic ES module loader
We found that systemjs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.