Get ready for NoFlo 1.0
After six years of work, and bunch of different projects done with NoFlo, we’re finally ready for the big 1.0. The two primary pull requests for the 1.0.0 cycle landed today, and so it is time to talk about how to prepare for it.
tl;dr If your project runs with NoFlo 0.8 without deprecation warnings, you should be ready for NoFlo 1.0
ES6 first
The primary difference between NoFlo 0.8 and 1.0 is that now we’re shipping it as ES6 code utilizing features like classes and arrow functions.
Now that all modern browsers support ES6 out of the box, and Node.js 8 is the long-term supported release, it should be generally safe to use ES6 as-is.
If you need to support older browsers, Node.js versions, or maybe PhantomJS, it is of course possible to compile the NoFlo codebase into ES5 using Babel.
We recommend new components to be written in ES6 instead of CoffeeScript.
Easier webpack builds
It has been possible to build NoFlo projects for browsers since 2013. Last year we switched to webpack as the module bundler.
However, at that stage there was still quite a lot of configuration magic happening inside grunt-noflo-browser. This turned out to be sub-optimal since it made integrating NoFlo into existing project build setups difficult.
Last week we extracted the difficult parts out of the Grunt plugin, and released the noflo-component-loader webpack loader. With this, you can generate a configured NoFlo component loader in any webpack build. See this example.
In addition to generating the component loader, your NoFlo browser project may also need two other loaders, depending how your NoFlo graphs are built: json-loader for JSON graphs, and fbp-loader for graphs defined in the .fbp
DSL.
Removed APIs
There were several old NoFlo APIs that we marked as deprecated in NoFlo 0.8. In that series, usage of those APIs logged warnings. Now in 1.0 the deprecated APIs are completely removed, giving us a lighter, smaller codebase to maintain.
Here is a list of the primary API removals and the suggested migration strategy:
noflo.AsyncComponent
class: use WirePattern or Process API insteadnoflo.ArrayPort
class: use InPort/OutPort withaddressable: true
insteadnoflo.Port
class: use InPort/OutPort insteadnoflo.helpers.MapComponent
function: use WirePattern or Process API insteadnoflo.helpers.WirePattern
legacy mode: now WirePattern always uses Process API internallynoflo.helpers.WirePattern
synchronous mode: useasync: true
and callbacknoflo.helpers.MultiError
function: send errors via callback or error portnoflo.InPort
process callback: use Process APInoflo.InPort
handle callback: use Process APInoflo.InPort
receive method: use Process API getX methodsnoflo.InPort
contains method: use Process API hasX methods- Subgraph
EXPORTS
mechanism: disambiguate with INPORT/OUTPORT
The easiest way to verify whether your project is compatible is to run it with NoFlo 0.8.
You can also make usage of deprecated APIs throw errors instead of just logging them by setting the NOFLO_FATAL_DEPRECATED
environment variable. In browser applications you can set the same flag to window
.
Scopes
Scopes are a flow isolation mechanism that was introduced in NoFlo 0.8. With scopes, you can run multiple simultaneous flows through a NoFlo network without a risk of data leaking from one scope to another.
The primary use case for scope isolation is building things like web API servers, where you want to isolate the processing of each HTTP request from each other safely, while reusing a single NoFlo graph.
Scope isolation is handled automatically for you when using Process API or WirePattern. If you want to manipulate scopes, the noflo-packets library provides components for this.
NoFlo in/outports can also be set as scoped: false
to support getting out of scopes.
asCallback and async/await
noflo.asCallback provides an easy way to expose NoFlo graphs to normal JavaScript consumers. The produced function uses the standard Node.js callback mechanism, meaning that you can easily make it return promises with Node.js util.promisify or Bluebird. After this your NoFlo graph can be run via normal async/await.
Component libraries
There are hundreds of ready-made NoFlo components available on NPM. By now, most of these have been adapted to work with NoFlo 0.8.
Once 1.0 ships, we’ll try to be as quick as possible to update all of them to run with it. In the meanwhile, it is possible to use npm shrinkwrap to force them to depend on NoFlo 1.0.
If you’re relying on a library that uses deprecated APIs, or hasn’t otherwise been updated yet, please file an issue in the GitHub repo of that library.
This pull request for noflo-gravatar is a great example of how to implement all the modernization recommendations below in an existing component library.
Recommendations for new projects
This post has mostly covered how to adapt existing NoFlo projects for 1.0. How about new projects? Here are some recommendations:
- While NoFlo projects have traditionally been written in CoffeeScript, for new projects we recommend using ES6. In particular, follow the AirBnB ES6 guidelines
- Use fbp-spec for test automation
- Use NPM scripts instead of Grunt for building and testing
- Make browser builds with webpack utilizing noflo-component-loader
- Use Process API when writing components
- If you expose any library functionality, provide an index file using noflo.asCallback for non-NoFlo consumers
The BIG IoT Node.js bridge is a recent project that follows these guidelines if you want to see an example in action.
There is also a project tutorial available on the NoFlo website.