Dynamically loads ES6 modules in browsers and NodeJS with support for loading existing and custom module formats through loader hooks.
ES6/ES2015 introduces native support for JavaScript modules, self-standing pieces of code which execute in their own scope and import values exported by other modules. Originally, the specification included the loader, and this polyfill was created to support those loader functions in current browsers and in NodeJS.
The final specification, though, only defines the language-specific semantics of modules, leaving implementations of the loading of those modules to separate specifications. The dynamic configurable loader is being specified at the WhatWG loader spec, and from version 0.50 this polyfill implements that.
Support for static loading of modules from HTML using <script type="module"> tags has also been added to the WhatWG HTML specification. This adapts the existing script-loading mechanism to include the loading of 'module scripts' together with all the other modules on which those module scripts depend. However, this currently has no interface with the WhatWG loader, and consequently with this polyfill. Eventually, both loading mechanisms should share a module registry, and the WhatWG loader resolution hooks should apply to the loading of module scripts as well.
- ES6 is now widely supported in the main browsers and in NodeJS.
- Browser support for module scripts is being implemented, currently behind flags; it's likely to be a while before this is usable in production systems.
- The WhatWG loader is not finalized and is unstable and liable to change. Consequently, this polyfill is also liable to change. This is unlikely to be implemented in browsers until stable.
- 'Provides a pipeline for on-demand, asynchronous loading of JavaScript modules'. This pipeline consists of URL resolution, plus three loading stages.
- Defines a
Loaderclass in the (new to ES2015)Reflectglobal object, withimport,resolveandloadprototype methods.importis the standard method for dynamically importing a module together with its dependencies, and combinesresolveandload.loadcan initiate the loading pipeline at any stage. What loading stages are needed depends on the host environment. - The
Loaderclass also includes a moduleRegistry, which is aSymbol.iterator. - Introduces a
Systemglobal object, with an instance ofReflect.Loaderas theloaderproperty; this is the default browser loader. In addition to theLoadermethods, this has prototype methods corresponding to the pipeline stages:resolve,fetch,translateandinstantiate. The last two are by default no-ops, but all these methods are programmable hooks, enabling the creation of custom loaders which can intervene in the pipeline by specifying custom code for one or more hooks. - Defines a
Moduleconstructor in theReflectglobal for dynamic construction of modules from within script or module code.
- Implements
Reflect.Loader, providing the ability for developers to create custom loader instances. - Implements the module registry
- Implements
Reflect.Module - Implements the
System.loaderdefaultReflect.Loaderclass instance, which means thatSystem.loader.importcan be used to dynamically load ES6 modules. - Until the parsing of
importandexportstatements are natively supported, supports both Traceur and Babel for transpiling these statements; this requires loading a large parser, so is not suitable for production use. - Provides a standards-based hookable loader, so users can create their own custom loaders with it.
- Fully supports ES6 circular references and live bindings.
- Targets modern browsers, all of which now support the great bulk of ES6.
- As the target browsers support ES6, no polyfills are included; applications wanting to support older browsers, such as IE, need to include polyfills for
Map,Symbol.iterator, andPromise, as well asURL(); https://cdn.polyfill.io provides a simple way to do this. - For use in NodeJS, support for
Map,Symbol.iterator, andPromiseis needed, so NodeJS v4+ is required (v6+ is recommended). - As only
importandexportare transpiled, those wanting to support older browsers should also pre-transpile any ES6 code into ES5. - What was previously in the
Systemobject, for exampleSystem.import, is now inSystem.loader(applications can of course supply an alias to ease the transition). - The previous
normalizeandlocatemethods have now been combined into theresolvemethod. - The
Moduleconstructor has been moved to theReflectobject. - Although the WhatWG loader will eventually define a
siteobject, which will probably include some kind of module name/URL mapping, this is not currently defined and so is not included in the current polyfill; this means there is no longer anybaseURLorpathssupport. For compatibility with module scripts, the default loader supports absolute URLs and relative URLs starting with/,./and../inimportstatements (this is relative to the URL of the importing module).
For an example of approaches for using the loader in production, see SystemJs which hooks in functionality such as supporting ES6 modules through the System.register transpiled format and its own custom module resolution mechanism.
Changing to the new loader spec is quite a lot of work, so contributions are welcome.
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using grunt.
Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!
##Contributors
Guy Bedford
Joel Denning
Luke Hoban
Addy Osmani
Peter Robins
Licensed under the MIT license.