connects via socket.io to an event source such as:
- chokidar-socket-emitter
- atom plugin jspm-dev-buddy
and reloads your ES6 modules as you change them. Similar to browserify hot module replacement, but running in your browser.
jspm i --dev systemjs-hot-reloader
Described by @guybedford himself:
http://jspm.io/0.17-beta-guide/hot-reloading.html
Use when your event emitter is available at http://localhost:5776 (the default). Include in your index.html
:
System.trace = true
System.import('./app.js')
At the top of your es6 code:
import 'systemjs-hot-reloader/default-listener.js'
Maps to empty module on production builds, so no needs for any if statements.
Include in your index.html
:
if (location.origin.match(/localhost/)) {
System.trace = true
System.import('capaj/systemjs-hot-reloader').then(function(HotReloader){
new HotReloader.default('http://localhost:8090') // chokidar-socket-emitter port
})
}
System.import('./app.js')
You can drop the if statement, but it is nice and convenient to load reloader only when on localhost. That way you can go into production without changing anything.
Boilerplate set up for hot reloading modules you can fork and use with 3 simple terminal commands(git clone XXX && npm i && npm start):
We're javascript programmers. We should not need to bundle our apps for development. Many folks dislike JSPM because of how slow it is. JSPM deserves another shot, because it can be faster, more robust and more reliable than most alternatives. This simple package proves it. Especially for larger codebases, SPAs and such-reliable hot reloadable modules are a necessray for meaningful feedback loop. Webpack hot reloading tools are hacky-very often a change in a source code doesn't manifestate after webpacks hot reload. This will never happen with module hot reload, because we're properly rerunning depency tree.
If you want some state to persist through hot reload, just put it in a module separate from the component. I personally use POJOs with observation, but you are free to use any kind of value store, as long as it sits in separate module from your reloaded component. Another way to do this is by adding a simple systemjs-hot-reloader-store utility.
When a change event is emitted on socket.io, we match a module in System._loader.moduleRecords. If a match is found, we then aggressively delete the changed module and recursively all modules which import it directly or indirectly via other modules. This ensures we always have the latest version of code running, but we don't force the browser into unnecessary work. Last step is to import again all modules we deleted, by calling import on the one that changed-module hierarchy will make sure all get loaded again.
See example: alexisvincent#23 (comment)
Any module, which leaves side effects in the browser and you want to hot-reload properly should export
export function __unload(){
// cleanup here
}
This is needed for example for Angular, which needs clean DOM every time it bootstraps.
This is also needed for some React components, like the Redux Provider and React Router. A crude way to force reloading of React components:
export function __unload() {
// force unload React components
ReactDOM.unmountComponentAtNode(DOMNode); // your container node
}
Most of the credit for this awesome engineering feat should go to Guy Bedford. He paved me a way, I simply followed it.
Tests are run as usual: npm test
- fork it
- write your code
- open PR
- lay back and if you want to speed it up, hit me up on twitter