This is a translation of the blog post by Guy Bedford - the main developer of such wonderful tools as JSPM - a package manager for browsers and NodeJS, which works on the basis of his brainchild SystemJS - the asynchronous loader JS modules of any known formats that can deal with cyclic dependencies , and which, in turn, is based on his brainchild, called es-module-loader , a polyfile for loading ES modules. As I understand it, the author pretty much rewrote SystemJS in this release, and it will be interesting to read about it to habrayamers.
SystemJS 0.20 has just been released - it is a complete reworking, as well as a specification correction, while the ES modules are already right here in the browsers .
SystemJS was originally developed back in 2013 for the jspm project, while RequireJS was the leading module loader. At the same time, ES6 was developing, and the ES6 modules still seemed to be an immaterial dream. The idea of SystemJS was simple and convincing: modules come to browsers, so we need to be able to download any module at any time from the browser, which would give a very simple development process.
With the advent of ES modules, it became clear that RequireJS is not going to stand the test of time. Creating your own loader based on the early specification of the ES module loaders, it became possible to help get tangible feedback on the work of the specification of the module loaders, as well as to get a stable loader in the end in order to work with it later.
Almost 4 years later, the project began to receive a little less than half a million downloads per month.
It was always following an unstable specification, which meant permanent changes breaking compatibility, but the goal of the project was to track all of these changes. Also, since specifications are mostly developed slowly, it was assumed that major changes would occur much less frequently than in most other projects.
Basically, SystemJS 0.20 represents the next release of the adjustment specification.
This post provides a summary of specification changes that have occurred lately, which will allow you to understand what to expect from the future browser specifications for loading modules, and SystemJS is right in all of this.
The road is almost clear for <script type="module">
and the dynamic import()
syntaxist, thanks to the authors of the specification for this hard work.
SystemJS has always been following the WhatWG bootloader specification, which actually stagnated for a while. What we saw with <script type="module">
and dynamic import()
are the fruits of the WhatWG bootloader, but coming from a small specification phase. These features were always present on the WhatWG roadmap and represented a gradual refinement of the functions of the loader.
Some of the features we have seen so far include:
Other features from the WhatWG bootloader specification, or what is still being discussed, but may appear in the future, include:
What is missing in the above functions is the hooks "normalize, find, receive, translate and instantiate." It became clear that this original canon would no longer be recycled or modified.
SystemJS goes very close to this path, so removing these hooks is one of the project-breaking changes to the project — you can no longer catch the System.fetch
or System.transate
. Instead of System[System.constructor.resolve]
and System.instantiate[System.constructor.instantiate]
, only two hooks are new.
In short, SystemJS 0.20 is based on the simplified assumptions of the resolver hook and the registry API in specification-based browsers. For more precise details about these APIs, you can study the module loader project at https://github.com/ModuleLoader/es-module-loader , which carefully details all these specification solutions and trade-offs.
The NodeJS side has made significant progress in adopting the modules path. The format of the SystemJS modules is largely consistent with these directions, but here there is one adjustment that is one of the biggest changes in the release that breaks compatibility.
This change is that named exports will no longer be allowed when importing a CommonJS module from an ES module, and all this is discussed at https://github.com/nodejs/CTC/pull/60/files#diff-2b572743d67d8a47685ae4bcb9bec651R217
That is, the construction import { name } from 'cjs.js
, where cjs.js is a CommonJS module - will no longer be supported, instead you will need to write import cjs from 'cjs.js'; cjs.name
import cjs from 'cjs.js'; cjs.name
. It will be a hard break, affecting NodeJS and Babel users in many places, so SystemJS is taking this punch right now.
We will continue to support the __esModule
flag in Interop, allowing you to raise named exports for similar situations.
So, if the cjs.js
module cjs.js
written as follows:
exports.__esModule = true; exports.name = function () { ... }
This will make it possible to get import { name } from 'cjs.js'
, even if cjs.js
is a CommonJS module, although in the long run it will also be eventually eliminated.
Since the project was reduced in size, the new production-build SystemJS was designed for optimal loading and performance on production.
In the development environment, the loader deals with the problem of loading unknown modules, i.e. we have a configuration problem - how do you get a package configuration that is not yet loaded? And for this reason, SystemJS received a complete configuration management system, including the ability to dynamically load configurations for files in the browser as part of the resolution, almost like package.json files that are loaded into NodeJS.
Removing all of these development conveniences reduces the production build to just 5KB. This volume provides loading of the System.register
and System.registerDynamic
, plus it contains functions of the base URL, module paths, maps, context maps, bundles and support for the dependency cache.
SystemJS aims to enable polyfiles for modules as they begin to be supported by browsers, while at the same time continuing to support the main features of maps, context maps and dependency caches.
For example, you might want to provide ES modules for browsers with support for ES modules,
At the same time, the SystemJS loader will work in older browsers based on polyfiles.
I refer to this approach as isomorphic browser modules, because using System.register
as the module format, the polyphile version can maintain the exact semantics of the execution of the ES module in supported browsers.
A demo was created at https://github.com/guybedford/isomorphic-browser-modules , based on the SystemJS 0.20 production build, which demonstrates how this module loading ES modules in Safari Technology Preview and returning back to SystemJS when native modules are not are supported.
SystemJS continues to go along this road, optimizing loading on production and working with modules in browsers, in environments of native modules, which we hope will also continue to evolve. One of the weaknesses of SystemJS at the moment is the lack of tools around the project from the development server to optimized production.
A lot of interesting work still needs to be done in this area, and, of course, there is always room for ideas and a contribution to the ecosystem of tools.
See my recent conversations at the conference with DotJS , where I lead a discussion about assembly optimization techniques for browsers that support ES modules.
Thanks to everyone who supported and invested in the development of SystemJS. If you have a desire to support the project in any way - we always have space for work, including cash donations are also welcome .
Source: https://habr.com/ru/post/320462/
All Articles