I was looking at some of the Stack Overflow noflo questions yesterday, and there were a few related to building NoFlo for the browser. This made me realize we haven’t really talked about the major change we made to browser builds recently: webpack.
Originally NoFlo was designed to only run on Node.js — the name itself is a portmanteau for Node.js Flow. But in 2013 we added support for Component.js to package and run NoFlo and its dependencies also on the browser.
This enabled lots of exciting things to happen: NoFlo example projects people could run simply by opening them in the browser, and building full-fledged client applications like Flowhub in NoFlo.
Unfortunately Component.js foundered and was eventually deprecated. Luckily others were picking up the ball — Browserify and webpack were created to fulfill a similar purpose, the latter picking up a lot of momentum. In summer 2016 we jumped on the bandwagon and updated NoFlo’s browser build to webpack.
Compared to Component.js, this gave several advantages:
- Separating module installation and builds — allowing us distribute also the browser modules via NPM
- No need to maintain separate
component.jsonmanifests on top of the existing
- Pluggable loaders providing a nicer way to deal with CoffeeScript,
.fbp, ES2015, and much more
- Code splitting for cleaner and more modular builds
And of course all other benefits of a thriving ecosystem. There are tons of plugins and tutorials out there, and new features and capabilities are added constantly.
The build process
In nutshell, making a browser build of a NoFlo project involves the following steps:
- Find all installed browser-compatible components using the fbp-manifest tool
- Generate a custom NoFlo component loader that requires all the component files and registers them for NoFlo to load
- Configure and run webpack with the application entry point, replacing NoFlo’s standard component loader with the generated custom one
Since we’re using NPM packages for distributing NoFlo modules for both Node.js and the browser, it is important to be able to communicate which platforms a component works with.
By default, we assume all components and graphs in a module work on both platforms. For many typical NoFlo cases this is true. However, some components may use interfaces that only work on one platform or the other — for example webcam or accelerometer access on the browser, or starting a web server on Node.js.
JSON graph files already have a standardized property for the environment information. But for textual files like components or
.fbp graphs, we added support for runtime annotations via a
@runtime comment string:
# This component only works on browser # @runtime noflo-browser
# This component only works on Node.js # @runtime noflo-nodejs
We also support a
@name annotation for naming a component differently than its filename. This is useful if you want to provide the same component interface on both platforms, but need separate implementations for each:
- CreateImage.coffee -
CreateImagecomponent for browsers
- CreateImage-node.coffee -
CreateImagecomponent for Node.js
For faster project setup, we have a template for creating NoFlo browser applications: noflo-browser-app. To use it, follow these steps:
- Fork the project
- Import the repository in Flowhub
- Make changes, synchronize to GitHub
- If you need additional modules, use
npm install --add
The project contains a fully working build setup, including Travis CI compatible test automation. If you supply Travis CI a GitHub access token, all tagged versions of your app will automatically get published to GitHub Pages.
The default setup enables live-debugging the app in Flowhub via a WebRTC connection:
If you want to disable the WebRTC runtime option, simply pass a
debug: false option to grunt-noflo-browser.
More details for using the template can be found from the project README.
In addition to building browser-runnable bundles of NoFlo projects, the grunt-noflo-browser plugin can — despite its name — be also used for building Node.js runnable bundles.
While a typical Node.js NoFlo project doesn’t require a build step, bundling everything into a single file has its advantages: it can reduce process start-up time drastically, especially in embedded devices with slow storage.
This is quite useful for example when building interactive installations with NoFlo. To make a Node.js build, add the following build configuration options:
noflo_browser: options: webpack: target: 'node' node: __dirname: true
In addition you’ll want to define any native NPM modules as webpack externals.
If you want to get started, simply fork the noflo-browser-app repo and start drawing graphs!
Update: If you don’t want to use Grunt, you can use noflo-component-loader to build a statically configured component loader and then use webpack directly. See NoFlo browser documentation for more information.