summaryrefslogtreecommitdiff
path: root/thirdparty/systemjs/docs/production-workflows.md
blob: 6af6989154fceca5818b9f93caeb00e1f3db9b89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
### Compiling Modules into a Bundle

[SystemJS builder](https://github.com/systemjs/builder) provides comprehensive support for compiling all 
module formats into a single bundle in a way that supports 
[circular references and zebra-striping](https://github.com/ModuleLoader/es6-module-loader/blob/v0.17.0/docs/circular-references-bindings.md).

It also offers the ability to [create self-executing bundles](https://github.com/systemjs/builder#self-executing-sfx-bundles) 
that can run without needing SystemJS present at all by embedding a micro-loader implementation.

### DepCache

An alternative to bundling into a single bundle is to leave files as separate for loading in production.

The depcache extension allows specifying the dependencies of all modules upfront through configuration so that loads can 
happen in parallel.

```javascript
System.config({
  depCache: {
    'moduleA': ['moduleB'], // moduleA depends on moduleB
    'moduleB': ['moduleC']  // moduleB depends on moduleC
  }
});

// when we do this import, depCache knows we also need moduleB and moduleC,
// it then directly requests those modules as well as soon as we request moduleA
System.import('moduleA')
```

Over HTTP/2 this approach may be preferable as it allows files to be individually cached in the browser meaning bundle 
optimizations are no longer a concern.

### Bundle Extension

It can be useful to load bundles of code on-demand instead of having them all included in the HTML page blocking the 
initial load.

The bundle extension will automatically download a bundle as soon as an attempt to import any module in that bundle is made.

```javascript
  // the bundle at build/core.js contains these modules
  System.config({
    bundles: {
      'build/core': ['jquery', 'app/app', 'app/dep', 'lib/third-party']
    }
  });
  
  // when we load 'app/app' the bundle extension interrupts the loading process
  // and ensures that build/core.js is loaded first
  System.import('app/app');
  
  // this way a request to any one of 'jquery', 'app/app', 'app/dep', 'lib/third-party'
  // will delegate to the bundle and only a single request is made
```

A built file must contain the exact named defines or named `System.register` statements for the modules
it contains. Mismatched names will result in separate requests still being made.

### CSP-Compatible Production

SystemJS comes with a separate build for production only. This is fully [CSP](http://www.html5rocks.com/en/tutorials/security/content-security-policy/)-compatible using script tag injection to load scripts, 
while still remaining an extension of the ES6 Module Loader.

Replace the `system.js` file with `dist/system-csp-production.js`.

If we have compiled all our modules into a bundle we can then write:

```html
  <script src="system-csp-production.js"></script>
  <script>
    System.config({
      bundles: {
        'bundle': ['app/main']
      }
    });
    System.import('app/main').then(function(m) { 
      // loads app/main from the app-built bundle
    });
  </script>
```

> Note the main build of SystemJS will also use script tag injection for AMD, register and global modules when it can for maximum CSP compatibility.
  It is typically just plugin loaders, CommonJS and custom global metadata options that cause XHR source-loading to be needed.