├── .gitignore
├── src
├── components.js
├── render.js
└── main.js
├── dist-esm
├── components.js
├── render.js
└── main.js
├── app.html
├── dist-system
├── components.js
├── render.js
└── main.js
├── package.json
├── modules-bootstrap.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/src/components.js:
--------------------------------------------------------------------------------
1 | export function homepageComponent (opts) {
2 | return `
${opts.message}
`;
3 | }
4 |
--------------------------------------------------------------------------------
/dist-esm/components.js:
--------------------------------------------------------------------------------
1 | export function homepageComponent (opts) {
2 | return `${opts.message}
`;
3 | }
4 |
--------------------------------------------------------------------------------
/src/render.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Eat your heart out React.
3 | */
4 | export function render (html) {
5 | document.body.innerHTML = html;
6 | }
7 |
--------------------------------------------------------------------------------
/dist-esm/render.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Eat your heart out React.
3 | */
4 | export function render (html) {
5 | document.body.innerHTML = html;
6 | }
7 |
--------------------------------------------------------------------------------
/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { homepageComponent } from './components.js';
2 | import { render } from './render.js';
3 |
4 | render(homepageComponent({
5 | message: `This application is rendered using
6 | ${self.__supportsScriptTypeModule ? 'ES modules' : ' System.register scripts'}.`
7 | }));
8 |
--------------------------------------------------------------------------------
/dist-esm/main.js:
--------------------------------------------------------------------------------
1 | import { homepageComponent } from './components.js';
2 | import { render } from './render.js';
3 |
4 | render(homepageComponent({
5 | message: `This application is rendered using
6 | ${self.__supportsScriptTypeModule ? 'ES modules' : ' System.register scripts'}.`
7 | }));
8 |
--------------------------------------------------------------------------------
/dist-system/components.js:
--------------------------------------------------------------------------------
1 | System.register([], function (_export, _context) {
2 | "use strict";
3 |
4 | function homepageComponent(opts) {
5 | return `${ opts.message }
`;
6 | }
7 |
8 | _export("homepageComponent", homepageComponent);
9 |
10 | return {
11 | setters: [],
12 | execute: function () {}
13 | };
14 | });
--------------------------------------------------------------------------------
/dist-system/render.js:
--------------------------------------------------------------------------------
1 | System.register([], function (_export, _context) {
2 | "use strict";
3 |
4 | /*
5 | * Eat your heart out React.
6 | */
7 | function render(html) {
8 | document.body.innerHTML = html;
9 | }
10 |
11 | _export("render", render);
12 |
13 | return {
14 | setters: [],
15 | execute: function () {}
16 | };
17 | });
--------------------------------------------------------------------------------
/dist-system/main.js:
--------------------------------------------------------------------------------
1 | System.register(['./components.js', './render.js'], function (_export, _context) {
2 | "use strict";
3 |
4 | var homepageComponent, render;
5 | return {
6 | setters: [function (_componentsJs) {
7 | homepageComponent = _componentsJs.homepageComponent;
8 | }, function (_renderJs) {
9 | render = _renderJs.render;
10 | }],
11 | execute: function () {
12 |
13 | render(homepageComponent({
14 | message: `This application is rendered using
15 | ${ self.__supportsScriptTypeModule ? 'ES modules' : ' System.register scripts' }.`
16 | }));
17 | }
18 | };
19 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "modules-iso",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "npm run copySrcToDist && npm run compileSrcToSystem",
8 | "copySrcToDist": "rm -r dist-esm ; cp -r src dist-esm",
9 | "compileSrcToSystem": "rm -r dist-system ; babel src --out-dir dist-system --plugins transform-es2015-modules-systemjs"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "systemjs": "^0.20.0-rc.1"
15 | },
16 | "devDependencies": {
17 | "babel-cli": "^6.18.0",
18 | "babel-plugin-transform-es2015-modules-systemjs": "^6.19.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules-bootstrap.js:
--------------------------------------------------------------------------------
1 | /*
2 | * SystemJS Modules bootstrap
3 | * This file is designed to run as both a module, a script, a worker module, and a worker script
4 | *
5 | * For use with it should be loaded via:
6 | *
7 | *
8 | *
9 | *
10 | * Works by checking if we are in a modules environment or not (feature-detectable by this === undefined)
11 | * If in a modules environment, it dynamically loads the modules main, otherwise it loads SystemJS and
12 | * then System.import loads the system module format main.
13 | */
14 | (function (topLevelThis) {
15 |
16 | var isModule = topLevelThis === undefined;
17 | var global = self;
18 |
19 | // this is needed for modules since document.currentScript doesn't seem supported
20 | // implementation just returns the first
31 | // -> load the main.js
32 | if (isModule) {
33 | var module = document.createElement('script');
34 | module.type = 'module';
35 | module.src = getCurrentModule().getAttribute('main');
36 | document.head.appendChild(module);
37 | global.__supportsScriptTypeModule = true;
38 | }
39 | // running as a
40 | // -> load SystemJS and then System.import('main.js')
41 | else if (!global.__supportsScriptTypeModule) {
42 | var systemScript = document.createElement('script');
43 | systemScript.src = document.currentScript.getAttribute('systemjs') || 'system.js';
44 |
45 | var mainSrc = document.currentScript.getAttribute('main');
46 |
47 | systemScript.addEventListener('load', load, false);
48 | document.head.appendChild(systemScript);
49 |
50 | function load () {
51 | systemScript.removeEventListener('load', load, false);
52 | document.head.removeChild(systemScript);
53 |
54 | SystemJS.import(mainSrc);
55 | }
56 | }
57 | })(this);
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # <script type="module"> Isomorphic browser modules workflow
2 |
3 | This project was created as a follow-up to discussions around how to load ES modules
4 | in modern browsers, while providing a fallback for older browsers that only
5 | support scripts.
6 |
7 | The approach here is to use a `modules-bootstrap.js` that is first attempted to load
8 | as a module and second as a script.
9 |
10 | Custom attributes on the scripts can then be used to point to the correct actual
11 | main entry points to be loaded once we know which loading mechanism to use.
12 |
13 | ### Demo
14 |
15 | Clone the repo and open `app.html` here when running a web server.
16 |
17 | In the latest Safari Technology Preview release with ES modules support, it will use
18 | the ES modules code, while in older browsers it will fallback to SystemJS production and
19 | System.register module format loading.
20 |
21 | To change the code and run a new build use `npm install && npm run build`.
22 |
23 | ### Bootstrap Explained
24 |
25 | The file `app.html` uses the following HTML for this bootstrap:
26 |
27 | ```html
28 |
29 |
30 | ```
31 |
32 | When `