Skip to content
This repository was archived by the owner on Jul 13, 2020. It is now read-only.

Commit 6721bfe

Browse files
committed
include docs
1 parent c9b3c2e commit 6721bfe

File tree

7 files changed

+539
-0
lines changed

7 files changed

+539
-0
lines changed

docs/circular-references-bindings.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
### Circular References & Bindings
2+
3+
#### Zebra-Striping
4+
5+
All [AMD](http://requirejs.org/docs/api.html#circular), [CommonJS](http://nodejs.org/api/modules.html#modules_cycles), and [ES6](https://github.com/ModuleLoader/es6-module-loader#circular-references--bindings) treat circular dependencies differently.
6+
Handling this problem is one of the innovations of the loader spec, using a technique called **zebra-striping**. This involves analyzing the dependency tree and forming alternate layers of ES6 / non-ES6 modules with circular references in each layer for linking.
7+
The layers are then individually linked, with the appropriate circular reference handling being done within each layer. This allows CommonJS circular references to interact with ES6 circular references. Inter-format circular references are not supported as they
8+
would be across layers.
9+
10+
This loader implementation handles zebra-striping automatically, allowing a loader like [SystemJS](https://github.com/systemjs/systemjs) to support all module formats with exact circular reference support.
11+
12+
#### ES6 Circular References & Bindings
13+
14+
ES6 circular references and bindings behave in the following way:
15+
16+
* Bindings are set up before module execution.
17+
* Execution is run from depth-first left to right on the module tree stopping at circular references.
18+
* Bindings are live - an adjustment to an export of one module affects all modules importing it, but it can only be modified in the defining module.
19+
20+
even.js
21+
```javascript
22+
import { odd } from './odd'
23+
24+
export var counter = 0;
25+
26+
export function even(n) {
27+
counter++;
28+
return n == 0 || odd(n - 1);
29+
}
30+
```
31+
32+
odd.js
33+
```javascript
34+
import { even } from './even';
35+
36+
export function odd(n) {
37+
return n != 0 && even(n - 1);
38+
}
39+
```
40+
41+
```javascript
42+
System.import('even').then(function(m) {
43+
m.even(10);
44+
m.counter;
45+
m.even(20);
46+
m.counter;
47+
});
48+
```

docs/loader-config.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
### baseURL
2+
3+
All modules are loaded relative to the `baseURL`, which by default is set to the current page path.
4+
5+
We can alter this with:
6+
7+
```javascript
8+
System.baseURL = '/js/lib/';
9+
System.import('module'); // now loads "/js/lib/module.js"
10+
```
11+
12+
> Note that using `System.import` to load URLs is not currently supported, instead use paths for this as documented below.
13+
14+
### Paths Implementation
15+
16+
The System loader provides paths rules used by the standard `locate` function.
17+
18+
For example, we might want to load `jquery` from a CDN location. For this we can provide a paths rule:
19+
20+
```javascript
21+
System.paths['jquery'] = '//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js';
22+
System.import('jquery').then(function($) {
23+
// ...
24+
});
25+
```
26+
27+
Any reference to `jquery` in other modules will also use this same version.
28+
29+
**Be careful**:When developing, System loader uses xhr method to load script from CDN site, so there might be some Cross-Origin problems.
30+
31+
It is also possible to define wildcard paths rules. The most specific rule will be used:
32+
33+
```javascript
34+
System.paths['lodash/*'] = '/js/lodash/*.js'
35+
System.import('lodash/map').then(function(map) {
36+
// ...
37+
});
38+
```
39+
40+
Rule specificity is determined by an exact paths match first, followed by the last deepest wildcard match.
41+
42+
### Custom Compilation Options
43+
44+
Custom [Traceur compilation options](https://github.com/google/traceur-compiler/wiki/Options-for-Compiling) can be set through `System.traceurOptions`, eg:
45+
46+
```javascript
47+
System.traceurOptions = { annotations = true };
48+
```
49+
50+
or if using Babel:
51+
52+
```javascript
53+
System.babelOptions = { experimental: true };
54+
```
55+
56+
### Finding the Transpiler
57+
58+
For Babel use the `browser.js` file contained in the `babel-core` npm module. For Traceur use the `traceur.js` file contained in the `traceur` npm module bin folder.
59+
60+
The transpiler is loaded as a module itself, so will follow normal paths rules.
61+
62+
To set custom paths to Babel or Traceur use paths configuration:
63+
64+
```javascript
65+
System.paths['traceur'] = 'path/to/traceur.js';
66+
```
67+
68+
Alternatively if you know that the transpiler will be needed, it will be detected from the global (`window[System.transpiler]`) when the first module is loaded, so can be loaded before ES6 Module Loader:
69+
70+
```html
71+
<script src="traceur.js"></script>
72+
<script src="es6-module-loader.js"></script>
73+
```

docs/loader-extensions.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
### Extending the ES6 Loader
2+
3+
The ES6 specification defines a loader through five hooks:
4+
5+
* Normalize: Given the import name, provide the canonical module name.
6+
* Locate: Given a canonical module name, provide the URL for the resource.
7+
* Fetch: Given a URL for a resource, fetch its content.
8+
* Translate: Given module source, make any source modifications.
9+
* Instantiate: Given module source, determine its dependencies, and how to execute it.
10+
11+
Variations of these hooks can allow creating many different styles of loader.
12+
13+
Each hook can either return a result directly, or a promise for the result.
14+
15+
To use custom loader hooks, one would typically override the System loader hooks on the `System` global directly:
16+
17+
```javascript
18+
// store the old normalization function
19+
var systemNormalize = System.normalize;
20+
// override the normalization function
21+
System.normalize = function(name, parentName, parentAddress) {
22+
if (name == 'my/custom/rule')
23+
return 'custom/name';
24+
else
25+
return systemNormalize.call(this, name, parentName, parentAddress);
26+
}
27+
```
28+
29+
### Custom Extension Example - Cache Busting Extension
30+
31+
```javascript
32+
var systemLocate = System.locate;
33+
System.locate = function(load) {
34+
var System = this; // its good to ensure exact instance-binding
35+
return Promise.resolve(systemLocate.call(this, load)).then(function(address) {
36+
return address + System.cacheBust;
37+
});
38+
}
39+
System.cacheBust = '?bust=' + Date.now();
40+
```
41+
42+
The above will add a customizable cache-busting query parameter to all requests. Custom filtering could even be added as well to only do this for certain requests.
43+
44+
### Creating a Custom Loader
45+
46+
A custom loader can be created with:
47+
48+
```javascript
49+
var myLoader = new LoaderPolyfill({
50+
normalize: ...,
51+
locate: ...,
52+
fetch: ...,
53+
translate: ...,
54+
instantiate: ...
55+
});
56+
```
57+
58+
### Loader Hooks
59+
60+
The signatures for all the loader hooks is provided below:
61+
62+
```javascript
63+
64+
/*
65+
* name: the unnormalized module name
66+
* parentName: the canonical module name for the requesting module
67+
* parentAddress: the address of the requesting module
68+
*/
69+
function normalize(name, parentName, parentAddress) {
70+
return resolvedName;
71+
}
72+
73+
/*
74+
* load.name the canonical module name
75+
* load.metadata a metadata object that can be used to store
76+
* derived metadata for reference in other hooks
77+
*/
78+
function locate(load) {
79+
return this.baseURL + '/' + load.name + '.js';
80+
}
81+
82+
/*
83+
* load.name: the canonical module name
84+
* load.address: the URL returned from locate
85+
* load.metadata: the same metadata object by reference, which
86+
* can be modified
87+
*/
88+
function fetch(load) {
89+
return new Promise(function(resolve, reject) {
90+
myFetchMethod.get(load.address, resolve, reject);
91+
});
92+
}
93+
94+
/*
95+
* load.name
96+
* load.address
97+
* load.metadata
98+
* load.source: the fetched source
99+
*/
100+
function translate(load) {
101+
return load.source;
102+
}
103+
104+
/*
105+
* load identical to previous hooks, but load.source
106+
* is now the translated source
107+
*/
108+
function instantiate(load) {
109+
// an empty return indicates standard ES6 linking and execution
110+
return;
111+
112+
// a return value creates a "dynamic" module linking
113+
return {
114+
deps: ['some', 'dependencies'],
115+
execute: function() {
116+
return loader.newModule({
117+
some: 'export'
118+
});
119+
}
120+
};
121+
}
122+
```
123+
124+
For a more in-depth overview of creating with custom loaders, some resources are provided below:
125+
126+
* The [System Loader implementation](https://github.com/ModuleLoader/es6-module-loader/blob/master/src/loader.js#L867)
127+
* [ES6 Loader API guide](https://gist.github.com/dherman/7568080)
128+
* [Yehuda Katz's essay](https://gist.github.com/wycats/51c96e3adcdb3a68cbc3) (outdated)

docs/overview.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
## Background
2+
3+
### Modules and Module Loaders
4+
5+
A module is simply a JavaScript file written with module syntax. Modules _export_ values, which can then be _imported_ by other modules.
6+
7+
[CommonJS](http://wiki.commonjs.org/wiki/CommonJS) and [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) JavaScript files are modules.
8+
9+
A module loader provides the ability to dynamically load modules, and also keeps track of all loaded modules in a module registry.
10+
11+
Typically, in production, the module registry would be populated by an initial compiled bundle of modules. Later in the page state, it may become necessary to dynamically
12+
load a new module. This module can then share dependencies with the initial page bundle without having to reload any dependencies.
13+
14+
Module code is treated differently to scripts due to the nature of exports and imports. This is why the `<script type="module">` tag is introduced to distinguish script code from module code.
15+
16+
### Module Names and baseURL
17+
18+
Module names are just like moduleIDs in RequireJS. Non-relative module names (not starting with `.`) are converted to a URL with the following rule:
19+
20+
```javascript
21+
URL = absolutePath(baseURL, ModuleName + '.js')
22+
```
23+
24+
Relative module names can be written `'./local-module'` to load relative to their parent module name. `..` syntax is also supported allowing easily portable modules.
25+
26+
## ES6 Module Syntax
27+
28+
### Exporting
29+
30+
ES6 module syntax is most similar to the `exports.method = function() {}` pattern in NodeJS of creating multiple named exports.
31+
32+
In CommonJS one might write:
33+
34+
```javascript
35+
exports.someMethod = function() {
36+
37+
};
38+
39+
exports.another = {};
40+
```
41+
42+
In ES6, this same code would be written:
43+
44+
exporter.js:
45+
```javascript
46+
export function someMethod() {
47+
48+
}
49+
50+
export var another = {};
51+
```
52+
53+
Notice that the name of the function, class or variable gets used as the export name.
54+
55+
### Importing
56+
57+
When importing, we import any exports we need by name, and can also choose to rename them:
58+
59+
importer.js:
60+
```javascript
61+
import { someMethod, another as newName } from './exporter';
62+
63+
someMethod();
64+
typeof newName == 'object';
65+
```
66+
67+
### Default Import and Export
68+
69+
Sometimes one doesn't want to write an import name at all. For this we can use the default export:
70+
71+
export-default.js:
72+
```javascript
73+
export default function foo() {
74+
console.log('foo');
75+
}
76+
```
77+
78+
import-default.js:
79+
```javascript
80+
import customName from './export-default';
81+
82+
customName(); // -> 'foo'
83+
```
84+
85+
### All Supported Syntax
86+
87+
There are a few other variations of module syntax, the full list of supported statements is listed below.
88+
89+
```javascript
90+
import 'jquery'; // import a module without any import bindings
91+
import $ from 'jquery'; // import the default export of a module
92+
import { $ } from 'jquery'; // import a named export of a module
93+
import { $ as jQuery } from 'jquery'; // import a named export to a different name
94+
95+
export var x = 42; // export a named variable
96+
export function foo() {}; // export a named function
97+
98+
export default 42; // export the default export
99+
export default function foo() {}; // export the default export as a function
100+
101+
export { encrypt }; // export an existing variable
102+
export { decrypt as dec }; // export a variable as a new name
103+
export { encrypt as en } from 'crypto'; // export an export from another module
104+
export * from 'crypto'; // export all exports from another module
105+
106+
import * as crypto from 'crypto'; // import an entire module instance object
107+
```
108+
109+
Note that any valid declaration can be exported. In ES6, this includes `class` (as in the example above), `const`, and `let`.

0 commit comments

Comments
 (0)