Conditional Loading
Conditional loading is supported in SystemJS and jspm 0.17 at the module tree level instead of through code conditionals.
The benefit of this approach is that conditional loading becomes a natural extension of the module
resolution process. SystemJS Builder is designed to handle conditional build trees
so that we can choose to build all possible conditional branches or just the branches we want by passing
the conditionals
build option.
The features shown in this section are SystemJS features more than jspm features, with SystemJS Builder doing all of the real work for us here.
So for a rather contrived example, let's say we wanted our Hello World
text to include a note as to whether
we are running in production or development.
We rewrite the src/component.js
file to import its text from a separate file:
import React from 'react';
import text from './text.js';
export class HelloWorld extends React.Component {
render() {
return <h1>{text}</h1>;
}
}
Where src/text.js
contains:
export default 'Hello World - Production';
Now to create a separate implementation of the text.js
file for development, edit src/text-dev.js
:
export default 'Hello World - Development';
If we load the app, we will get the production version by default.
To inform SystemJS to use the development version in development we can edit the package configuration
(as we did in the Package Configuration section) in jspm.config.js
to include a conditional package map:
SystemJS.config({
...
packages: {
"jspm-react-component": {
...
"map": {
"./text.js": {
"~production": "./text-dev.js"
}
}
},
...
}
});
The ~production
syntax above means the NOT production condition will use
src/text-dev.js
instead of text.js
.
We can add multiple conditions to the conditional package map, which will match
from first to last with the path being left unchanged as the default fallthrough.
By editing the production
boolean property in jspm.browser.js
, we can now
control which branch of the component text SystemJS will load.
The important point to note about conditional loading is that conditions are fixed
for the duration of the execution environment.
The environment is either node
or the browser
(although environments like Electron are both node
and browser
), either running in production
or not, until we explicitly restart the execution.
By default when we bundle, we will only bundle the production branches.
Run jspm bundle jspm-react-component - react
to see how the tree excludes the text-dev.js
branch:
Building the bundle tree for jspm-react-component - react...
jspm-react-component/component.js
jspm-react-component/text.js
npm:systemjs-plugin-babel@0.0.2.json
npm:systemjs-plugin-babel@0.0.2/babel-helpers/classCallCheck.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/createClass.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/inherits.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/possibleConstructorReturn.js
ok Built into build.js with source maps, unminified.
If we instead run jspm bundle jspm-react-component - react --dev
then bundling will
explicitly include the development branch only.
To include both possible branch outcomes in the bundle, use jspm bundle jspm-react-component - react --dev --production
:
Building the bundle tree for jspm-react-component - react...
jspm-react-component/component.js
jspm-react-component/text.js
jspm-react-component/text-dev.js
npm:systemjs-plugin-babel@0.0.2.json
npm:systemjs-plugin-babel@0.0.2/babel-helpers/classCallCheck.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/createClass.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/inherits.js
npm:systemjs-plugin-babel@0.0.2/babel-helpers/possibleConstructorReturn.js
ok Built into build.js with source maps, unminified.
In the same way that we have used production
in this example, we can also use node
and browser
as conditional branches that conditionally load and build.
Conditional loading also applies to jspm build
, but we must always build an exact
branch solution when using jspm build
. That is, we must build for dev or production,
exclusively, browser or node exclusively.
For example, to build a Node-only single-file production version of React:
jspm build react --node --production --format cjs react-node-production-build.js
We can then test this with:
node -e "console.log(require('./react-node-production-build.js'))"
to see that React has been correctly built and linked for running in Node in production.
By replacing --node
with --browser
in the above build we can also create a
Browserify-style build of React for production, which will then only include all the
necessary Browserify shims for the NodeJS core modules.