BuckleScript 4.0.0 (Part One)
bs-platform
4.0.0 is released! It has some nice features that we want to share with you, a more detailed list of changes is available here
In this post, I will talk about a new development workflow, all toolchains are self-contained in bs-platform
, Cristiano will talk about the new runtime encoding for optional.
A simple approach to accelerate feedback loop in a reliable way
For mordern day-to-day development, developers expect that whenever files are changed, the build process is re-triggered automatically and browser reloaded instantly, this feedback loop should be quick enough to make developers not get distracted.
What we have before this release is as below:
- Source file changes detected by bsb watch mode, rebuild
- Webpack noticed JS files modified, rebundle and update the browser state
Both bsb
and webpack
has a watch mode, but they are architectured in fundamentally different ways that they achive different levels of reliability.
In bsb
watch mode, there is no long running memory-hungry process, so whenever a file changed, a fresh process is started very fast and dies quickly, our experiment shows that in practice, a long running bsb process can work for a week without going into bad state, and such feedback loop is still instant.
Webpack
holds lots of objects in memory and running for a longtime, it results in less reliability and OOM from time to time.
Another complexity introduced by a JS bundler is that it explodes users directory structure, for beginners trying to get started with bucklescript, installing such huge amount of directories is intimidating. In a slow network, this used to result in installation failure.
We understand that existing JS bundler has a huge ecosystem and it is invaluable in production mode, but we are exploring whether we can provide similar or even more reliable development experience without introducing such complexity.
Below is a new workflow we are exploring in this release:
NodeJS module loader in browser
Instead of bundling the modules like normal bundlers, we provide a NodeJS module loader so that it simply reloads the module without bundling.
Note ideally this can be achieved using ES6 module spec, however, it is not practical due to following reasons:
- Most dependencies are not strictly ES6 compilant, this is true even for libraries authored in ES6 style
import {createElement} form "react" ; // not es6 compliant
import {createElement} from "node_modules/react/index" // not es6 compilant
import {createElement} from "./node_modules/react/index.js" // correct es6 module
- ES6 modules does not allow an indirection, by introducing our own NodeJS module loader, we have an indirection and more meta-data about each module, so that we can do more reflection work in the future.
Loading in clean state without packing seems to introduce some redundant work, but on the contratry, it is very fast, it used to load 200 modules under 150ms, even better, since there is no cached state in a long running process, it is much more reliable.
WebSocket integration with bsb
We need a mechanism to communciate between browser and the build system so that whenever a rebuild finished, the browser get notified.
Instead of introducing more dependencies, we implemented a minimal websocket interface so that whenever a rebuild finishes, the weboscket clients which subscribe the port will get notified.
To conclude and try it out
So the proposed new work flow is as below: whenever a source file is changed, the bsb rebuild, if it build successfully, it will notify the browser to reload the NodeJS modules directly.
All the devtools are provided by bs-platform, the good thing is that there is no long running memory-hungry process, so that we expect it will deliver a more reliable and consistent experience.
You can try it out in bs-platform@4.0.0
bsb -init test -theme react-lite
cd test
npm install
npm start
http-server # start a http server
open localhost:port/index.html
, changes the reason source code and expect the browser show the changes.