In the beginning of October, I stopped bundling Mopidy.js with the Mopidy Python project and thus had to update the Mopidy.js documentation. While doing so, I tried to run the test suite, written using Buster.JS, which has been abandoned for a few years. To no avail, npm and Yarn were not able to install the library’s development dependencies.
I asked a couple of coworkers for advice on what to replace Buster.JS with that could test a library in both Node.js and the browser, and what they would use instead of Browserify today. I was quickly pointed towards Jest for testing and Parcel for zero-configuration builds.
Porting the full test suite–three times the size of the library–to Jest was work, but mostly mechanical work. The only part I needed to read a bit up on was Jest’s mocking capabilities compared to Sinon.JS.
Modernizing development tooling
After getting the test suite running again the modernization continued.
All code was reformatted with Prettier. This required almost no configuration, once figuring out how to make ESLint and Prettier stay friends. However, the experience of getting an entirely consistent code style without any effort is priceless. I can accept most differences from my previous styles in exchange for not having to do the work myself and not having to enforce that my contributors and coworkers do the same. Formatters like Prettier, Black,
rustfmt are here to stay and will probably be an integral part of all new programming languages.
Removing Buster.JS and JSHint reduced the project’s Grunt setup a bit. The move from Browserify for browser builds and Uglify for minification to Parcel lead to the removal of Grunt entirely, and the replacement of a monitor height or two of Grunt config with the command
parcel build src/mopidy.js.
Reducing runtime dependencies
The time had now come to runtime dependencies.
Since the last release of Mopidy.js in 2015, ES6’s Promise implementation has become quite universally available. Thus, when could be replaced with Promise, shrinking the minified library from 42 kB to 12 kB.
BANE, an event emitter library that was part of the now-dead Buster.JS testing tool, was replaced with the
EventEmitter implementation from Node.js’ standard library. Parcel helpfully and entirely automatically included the
EventEmitter implementation from Node.js as part of the web bundle, without having to add a dependency on one of the npm packages that has extracted this lib from the Node.js standard library.
Making demo applications
Once everything was modernized, I added two demo applications to the project.
The web-based application is served by Parcel’s web server. The configuration needed? Add
parcel examples/web.html as the
start script in
package.json and I was done:
yarn start now runs the demo web app on
http://localhost:1234, with automatic code reloading on source changes.
For the Node.js console application, I quickly remembered that while promises are better than callbacks, they can still quickly become quite mind-boggling to work with. Enter async/await, spreading like wildfire from language to language the last few years, and fully available in Node.js since 2017. You just have to remember to create all the promises you need, and only then
await them. This makes it possible for the promises to be fulfilled in parallel instead of sequentially, avoiding that the sequential round trip times to the server add up.
Somewhere around here I read a bit up on TypeScript and tested out porting the library to TypeScript with great help from VS Code. Due to Mopidy.js’ tiny static API and quite large dynamic API, automatically generated based on the API description retrieved from the server, this didn’t seem a worthy path to go down this time around. However, the experience was a good one, and I’ll probably revisit TypeScript in the future on other projects.
Finally, the Mopidy.js docs were moved from the Mopidy docs to the Mopidy.js project and updated accordingly. Being used to writing docs in Sphinx, Markdown’s lack of features like generating a table of contents can feel limiting. Of course, several VS Code extensions can automatically generate a ToC and keep it up to date every time you save your file.
I’d go as far as claiming that the exercise of modernizing Mopidy.js and its development tooling was, at times, fun and inspiring.
Here’s to four more years of Mopidy.js. Then I might be back with a port to WebAssembly, implemented in Rust, or a language yet to be designed. We’ll see!