I recently worked on a small project where I had free reign to use whatever technology I wanted. It was an internal project, so as long as I chose a language people knew and documented it I could go along my merry way.

I've been wanting to try new features in Node.js, so I decided to take this opportunity to use node v9.2.0 (the latest cutting-edge at the time of this post). It was an interesting experience to say the least.

Native Modules

Using the --experiement-modules flag allows one to use the import and export syntax when it comes to modules. Let's take a quick look.

without the flag

const fs = require('fs');

// .... something ...

module.exports = somethingICreated;  

with the flag

import fs from 'fs'

// .... something ...

export default somethingICreated;  

If you do browser work or have looked at any React or "new" framework docs, you've probably seen this syntax before.

Personally, I really like this syntax. It unifies the work I do in the browser, using babel, and the work I do in node.

Testing (with --experiement-modules flag)

I usually start my project by setting up my testing framework and such, but I soon found out that using the .mjs extension doesn't really work with any test frameworks. Mocha and Jest are my gotos, but they don't seem to support it yet judging from issues on their repos.

So, unfortunately, this meant testing was out the window. A few times I caught myself thinking, "my test would've caught that one," but it was a simple internal project and easy to reason about.

Async/Await

This was one of the features that I really wanted to try. This project interacted with two APIs and involved a good amount of async tasks. It was the perfect opportunity to make the leap from the Promise API to Async/Await.

Overall, it was a pretty easy concept to wrap my head around. You can search Google if you want to know what the syntax looks like or how it differs from the Promise API. Here's one* for instance.

The one thing I'm still not sure about is the best way to do error handling. It's suggested that using try/catch is the way to go, but I found a lot of things lacking when using this method.

Unfortunately, I think my problems were compounded by using native modules, as the stack traces were not very helpful. Who knows, maybe I was doing something wrong.

util.promisify

While this may not be new, I thought it was pretty cool. What does it do? It "promisifies" a nodejs error first callback style function. This means that you can use a function like fs.writeFile using promises, instead of succumbing to callback hell.

The one weird thing I found was that you need to fill in the optional arguments, up until the callback, or you will get an error and the method may not work correctly.

Take below for example:

const writeFile = util.promisify(fs.writeFile);

await writeFile(berksFile, berksFileTemplate, { encoding: 'utf-8' });  
// or 
writeFile(berksFile, berksFileTemplate, { encoding: 'utf-8' })  
  .then(() => {})
  .catch(err => console.log(err));

If you do not provide the encoding information, in this case, the most basic being an empty object literal, you will get an error or a deprecation warning.

In the end

Overall I think the new features in nodejs are very useful and nice to see.

I think taking all of them on at once may have been a bit much. In my case, problems with one feature probably exacerbated problems with another.

Devs should definitely devote some time to learn these new features. They are very useful and are probably going to be used a lot in the future. I'll hop on the bandwagon and say, "don't use flagged features in prod or something that is vital."

Until next time...

* I'm putting a link here just cause it shows the differences, not because I agree with the premise