Giter Site home page Giter Site logo

systemjs's Introduction

SystemJS

Gitter Backers on Open Collective Sponsors on Open Collective Downloads on JS Delivr

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.

Sponsors

Support SystemJS by becoming a sponsor. Your logo will show up here with a link to your website.

Backers

Thank you to all our backers! ๐Ÿ™ [Become a backer]

Overview

1. s.js minimal production loader

The minimal 2.8KB s.js production loader includes the following features:

  • Loads System.register modules, the CSP-compatible SystemJS module format.
  • Support for loading bare specifier names with import maps via <script type="systemjs-importmap">.
  • Supports hooks for loader customization.

2. system.js loader

The 4.2KB system.js loader adds the following features in addition to the s.js features above:

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) or the network, with included caching that respects the Content-Type header.
  • Import Maps (via the applyImportMap api).
  • Tracing hooks and registry deletion API for reloading workflows.
  • Loading global modules with the included global loading extra.

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 register supports System.register('name', ...) named bundles which can then be imported as System.import('name') (as well as AMD named define support)
  • Dynamic import maps support. This is currently a potential new standard feature.

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, .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.

SystemJS Babel

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.

Performance

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

Getting Started

Introduction video.

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

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:

<script src="system.js"></script>
<script type="systemjs-module" src="/js/main.js"></script>
<script type="systemjs-module" src="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:

<script src="system.js"></script>
<script type="systemjs-importmap">
{
  "imports": {
    "lodash": "https://unpkg.com/[email protected]/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 Support

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/[email protected]/js/browser/bluebird.core.min.js"><\/script>');
  if (typeof fetch === 'undefined')
    document.write('<script src="https://unpkg.com/[email protected]/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.

Note on Import Maps Support in IE11

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.

Community Projects

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

  • beyondjs.com -TypeScript first meta-framework for universal microfrontends/micronservices.
  • esm-bundle - list of System.register versions for major libraries, including documentation on how to create a System.register bundle for any npm package.
  • 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.
  • @wener/system - hooks to make System works with npm registry & package.json}

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 [email protected], 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 } }
    ]
  }
}

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).

Contributing to SystemJS

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

Changes

For the changelog, see CHANGELOG.md.

License

MIT

systemjs's People

Contributors

asapach avatar b-strauss avatar blink1073 avatar blittle avatar briandipalma avatar casperlamboo avatar crisptrutski avatar fictitious avatar guybedford avatar joeldenning avatar josh avatar justinbmeyer avatar kouts avatar larsdenbakker avatar majhork avatar majorbreakfast avatar matthewbauer avatar matthewp avatar meomix avatar mk-pmb avatar munter avatar orkon avatar peteruithoven avatar probins avatar simonykq avatar stefanr avatar theefer avatar unional avatar vladima avatar wenerme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

systemjs's Issues

Named Modules

From what I can tell with a quick look at the source, there's no support for named AMD modules. Is there any plan to add this? It's particularly important for supporting tools like r.js which encode the module name in the define call during the build process.

If there's no planned support for this, how does one go about packaging multiple modules in a single file? I thought I saw syntax for that in the ES6 spec, but wasn't sure if the es6 shim supported it and wasn't sure if there was support for non-es6 named modules. I tried calling System.set with a module literal, but importing it by the registered name didn't work because of the normalize/resolve logic in the custom loader I suppose. Any thoughts on this?

Implement location mirrors

endpoints: {
  github: ['https://first-mirror.com', 'https://some-mirror.com']
},

Optionally allow multiple location mirrors, chosen randomly to split global load, favouring using a mirror domain that is already used by another endpoint (to use the same SPDY connection).

Still need to consider these concepts in more details, when mirrors start being created.

Be able to undef a module after an error?

(I'm talking about the dynamic require case here)
With requirejs, this was my errback function:

var failedId = err.requireModules && err.requireModules[0];
requirejs.undef(failedId);

What's the workflow when you get an error loading a module with the jspm loader? Do one has to undefine it somehow?

AMD detection on uglifyed files

Hi! I recently had an issue that was kinda had to diagnose, and I thought it would be worth documenting.

System.js detects correctly cjs-style amd:

define(function(require) {
  var $ = require("jquery");
});

However, after uglifycation, the above file might end up like this:

define(function(a) {
  var $ = a("jquery");
});

Which, in turn, isn't detected correctly. To sidestep the problem, I've told uglifyjs to not mangle variables named require:

uglify: {
  mangle: {
    except: ['require']
  }
}

Do you think it is worth adding to the README or a wiki page?

Predefined modules are being reloaded

I'm using almond.js instead of require.js. I've all the modules inlined and loaded. When I try to call jspm.import of one of the defined modules, it tries to load it again.

Conditional loading

Outside the scope of the current plugin system... perhaps consider a natively supported loading syntax for conditionals like:

jspm.import('some/condition ? some/module : another/module');
jspm.import('!some/condition ? some/module');
jspm.import('some/condition ? some/module, another/module');

For inline conditions, these can still be provided by:

jspm.set('some/condition', new Module({ default: someInlineFunction() });

move back to package-based config

  map: {
    'jquery': 'github:jquery/[email protected]'
  },
  endpoints: {
    'github': 'https://github.jspm.io'
  },
  packages: {
    '.': {
      shim: {
        'app/angular': ['jquery']
      }
    },
    'github:jquery/[email protected]': {
      format: 'amd',
      main: 'jquery',
      map: {
        '*': 'js/*'
      },
      dependencyMap: { 
        'sizzle': 'github:jquery/[email protected]'
      }
    }
  }

The config would apply:

  • global
  • package

map would be identical in operation to global map, but just concatenated with the package name:

map({
  'github:jquery/[email protected]/*': 'github:jquery/[email protected]/js/*'
});

package-level dependencyMap replaces contextual map.

Multiple Imports withing the same import()

Hey Guy

Just started to give JSPM a try. :-)

Is it possible to import multiple libraries at the same time sort of like

jspm.import(['this', 'andthis', 'andthis'] function(th, tha, tha2) {
// work it
} )

I'd like to use it this way then pass them to the Polymer constructor so the libraries can be used in the ShadowDOM scope.

Thanks again
Alessandro

Using jspm-loader standalone

Is it possible to use the library without the ES6-Loader polyfill? I'm thinking on a simpler drop-in replacement for RequireJS.

Support X-Submodules

Create a new fetch function that will check the response headers for X-Submodules. When found, it is parsed as a comma-separated list of double-quoted relative module names to the current module name, which are then requested via an immediate import in the fetch function.

LICENSE?

you must include license text for MIT license

importURL

If URL's are not supported by the standard System loader, then we can implement an importURL method to allow loading URLs.

Gist endpoint?

gist.github.com can be used as a place for storing individual modules (or other types of file) as opposed to packages stored in github repos, so I'm thinking it might be useful to have this as an endpoint?

Global handling

How to deal with a library that expects a global, when the underlying library has a global and an export mode as separate things?

We may need to allow a more RequireJS-identical shim.

Mention RequireJS test-coverage/surface covered

I believe you may have previously mentioned that you had good surface coverage of many RequireJS tests. If so this would be worth mentioning in the README :)

If not and I'm completely incorrect, please feel free to close or maybe strike towards that being a goal!

Module Load Hook

First off...this project looks great. I thought I was going to have to write this myself, so I'm very happy right now that I do not ๐Ÿ˜„

I can tell from the docs that it does just about everything I need. I do have one additional requirement that I wasn't sure it supported. I'm in need of a module load hook. I'd like to be able to add a function either to jspm's loader or hook into the es6 loader so that I can grab the module instance after it's instantiated. I then need to tag each module with its module id in a hidden property. So, obviously I need access to the module instance and some metadata after it's assembled but before anything else uses it.

Is this supported by the es6 loader through one of its callbacks? If not, is it supported by jspm? If not, how can I tempt you into adding it? ๐Ÿ˜‰

consider bundles as scripts

What if instead of fetching a bundle as a module, it always did script injection?

This way bundles are by default CORS compliant.

The minimal production loader becomes the scenario where all code is loaded from a bundle, hence we no longer need any XHR fetch, translate or custom instantiate code since everything is loaded from the instantiate cache.

AMD Issues

Here's my AMD module define:

app.js

define(function () {
    return {
        start: function () {
            console.log("App Started");
        }
    };
});

Here's my ES6 module:

main.js

import app from 'app';

app.start();

I have some map config setup and I've confirmed that is indeed loading and parsing and evaluating both files. However, in main.js the 'app' is always undefined. It seems that the wrong code path is being take in the link function of the loader such that the returned object from the AMD module is not being set up as the default export. Am I missing something?

Support for markdown?

Would it be easy to add a plugin which takes a markdown file from an endpoint like github, and converts it into html: a buildConfig for html snippets?

Bower install

On the "Getting started" page:
https://github.com/systemjs/systemjs#getting-started

It states:
"Download es6-module-loader.js and traceur.js from the ES6-loader polyfill and locate them in the same folder as system.js from this repo.
Then include dist/system.js with a script tag in the page:"

  1. The traceur.js resolves into a 404 and does not exist physically in the repo.
  2. Would'nt it be better just to "bower install system.js" and be done?

Thanks

implement non-static alternative to "transpiled"

The issue is that we have no way to know whether we should use the default as the main module for an ES6 transpiled dependency of an AMD file that was transpiled from ES6.

Perhaps we can include meta on all AMD and CommonJS modules to ensure they are always returned by their default property:

new Module({
  __defaultOnly: true
  default: 'here'
});

Then in AMD and CommonJS we only use the default when the __defaultOnly meta property is set.

Location / Endpoint Configuration

Firstly, change the name of locations to endpoints.

Then, allow the following configuration options:

endpoints: {
  github: {
    format: 'detect' / 'es6' / 'amd' / 'cjs' / 'global',
    location: 'https://github.jspm.io',

    repoDepth: 1, // allows specifying a standard main form for the location
    main: 'main'
  }
}

The standard form will still work though as well:

endpoints: {
  github: 'https://github.jspm.io'
}

module x from y support

The latest version of es6-module-loader supports the "module x from y" syntax to retrieve the entire module instance object. I believe this could be used to get around some of the problems with AMD modules. However, it doesn't seem to work in jspm. My guess from a quick look is that the module is incorrectly being interpreted as a cjs module and thus esprima is not being used to parse translate the module.

Importing globals with ES6 syntax

Hi!

I just noticed there's an inconsistency between consuming an AMD module and a globals "module". Suppose we've two files, amd.js and global.js:

amd.js

define(function() {
  return function theAnswer() {
    return 42;
  };
});

global.js

window.theAnswer = function() {
  return 42;
};

In my view, they are conceptually the same. However, they can't be used interchangeably:

es6.js

  import amdAnswer from "./amd";
  console.log(amdAnswer()); // Works

  import globalAnswer from "./global";
  console.log(globalAnswer()); // Breaks with "undefined is not a function"

This happens because the return value from the AMD module is placed on the default export, while the global is exported as the module itself.

I suspect the most forward-compatible solution is to change the global-loading code to place the variable's value on the default export. I could be overlooking something, though :)

IE compatibility

Hi,

Does the current version of SystemJS built with support of Internet Explorer 8?

Questions

Hi,
I just read through your module and I'm excited about the features and flexibility.
I consider using it instead of require.js.
I have two questions:

1.) Can you make a hint regarding browser compatibility?

2.) I don't get what you mean by "the CDN". Which CDN is meant?
Can I specify my own CDN (provider)?
Also I don't understand the example with

<link rel="stylesheet" href="https://github.jspm.io/hakimel/reveal.js/css/reveal.css"></link>

This is just a plain link, I don't see jspm in the picture.

Thanks

Requesting use case for css-required files

When loading github:FortAwesome/[email protected]/css/font-awesome.css!

It would also need to load the font files in that repo. I see that this is acknowledged but not yet implemented. Per the page's instructions,

Repo and version matched, but path "fonts/fontawesome-webfont.woff?v=4.0.3" not found. Symlinks and submodules not currently supported, file an issue to request this use case.

I am hereby requesting. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.