mirror of
https://github.com/systemjs/systemjs.git
synced 2026-01-25 14:57:38 +00:00
89 lines
3.2 KiB
Markdown
89 lines
3.2 KiB
Markdown
### Compiling Modules into a Bundle
|
|
|
|
[SystemJS builder](https://github.com/systemjs/builder) provides comprehensive support for compiling all
|
|
module formats into a single bundle.
|
|
|
|
It also offers the ability to [create statically optimized modules](https://github.com/systemjs/builder#self-executing-sfx-bundles)
|
|
that can run without needing SystemJS present.
|
|
|
|
### Loading Bundles
|
|
|
|
Once a bundle has been created, it will be populated with a series of `System.register('module-in-bundle', ...` declarations.
|
|
|
|
We include the bundle generated by SystemJS builder with a script tag after SystemJS, and before importing the module we want to import:
|
|
|
|
```html
|
|
<script src="system.js"></script>
|
|
<script src="system-config.js"></script>
|
|
<script src="bundle.js"></script>
|
|
<script>
|
|
SystemJS.import('module-in-bundle');
|
|
</script>
|
|
```
|
|
|
|
When the bundle executes, it declares the bundle modules into the SystemJS loader registry. When importing `module-from-bundle`,
|
|
it will then use the version defined by the bundle.
|
|
|
|
Alternatively, we could import the bundle itself via `SystemJS.import`, but then need to nest the import statements for the code to work properly:
|
|
|
|
```javascript
|
|
SystemJS.import('/bundle.js').then(function (m) {
|
|
// (the bundle itself is an empty module m)
|
|
return SystemJS.import('module-from-bundle');
|
|
})
|
|
```
|
|
|
|
### Bundle Extension
|
|
|
|
For loading bundles of code on-demand for chunked loading use cases, instead of nesting the `SystemJS.import` statements, we can use the `bundles`
|
|
configuration.
|
|
|
|
The `bundles` configuration allows determining which modules to load from which bundle:
|
|
|
|
```javascript
|
|
// the bundle at build/core.js contains these modules
|
|
SystemJS.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
|
|
SystemJS.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.
|
|
|
|
Typically we only want the `bundles` config for lazy-loaded code.
|
|
|
|
### DepCache
|
|
|
|
An alternative to bundling into a single bundle is to leave files as separate for loading in production.
|
|
|
|
The issue with loading modules as separate files is that dependencies are downloaded as they are discovered, leading
|
|
to a load time of `latency * module tree depth`.
|
|
|
|
The depcache extension allows specifying the dependencies of all modules upfront through configuration so that loads can
|
|
happen in parallel.
|
|
|
|
```javascript
|
|
SystemJS.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
|
|
SystemJS.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.
|