Skip to content

Instantly share code, notes, and snippets.

@rauchg
Last active September 30, 2024 17:11
Show Gist options
  • Save rauchg/8199de60db48026a6670620a1c33b700 to your computer and use it in GitHub Desktop.
Save rauchg/8199de60db48026a6670620a1c33b700 to your computer and use it in GitHub Desktop.

Minimum Viable Async with Node 6

With the release of Node 6.0.0, the surface of code that needs transpilation to use ES6 features has been reduced very dramatically.

This is what my current workflow looks like to set up a minimalistic and fast microservice using micro and async + await.

The promise

To write a service that displays the current Bitcoin price we should be able to write an lib/index.js like so:

import request from 'request-promise';
const URL = 'https://api.bitcoinaverage.com/ticker/global/USD';
export default async () => {
  const price = await request(URL, { json: true });
  return `The price is ${price.last} as of ${price.timestamp}`;
}

and to run it with node run.js:

import serve from 'micro-core';
import api from './lib';
serve(api).listen(8080, (err) => {
  if (err) throw err;
  console.log('Listening on *:8080'); 
});

Minimum viable Babel

The only notable feature that’s missing in V8 as far as ES6 support is import and export (i.e: the module syntax).

async and await is coming to V8 but it’s not ready yet. This means that our babel configuration in package.json is simply down to two modules.

{
  "babel": {
    "plugins": [
      "transform-es2015-modules-commonjs",
      "transform-async-to-generator"
    ]
  }
}

Since we can compile to generators instead of regenerator and Promise is built-in, Babel can do exclusively the job it was designed to do: transform code. No babel-runtime!

babel-node is back

If you’ve used babel-node in the past you probably noticed it could be slow and resorted to more complicated pipelines with gulp or make.

Since the amount of work babel has to do has now been decreased to a minimum, it’s now feasible to run your programs with it again!

During development you could then execute.

$ babel-node run.js

When you make a change, you just re-run your code without an explicit build step and with great support for source maps.

Production optimizations

To optimize startup time to the fullest, you probably still want to pre-compile before you ship. For that, you can define a task like this:

"scripts": {
  "build": "babel lib --out-dir dist"
}

If you plan to publish, make sure that you only publish that directory:

"files": ["dist"],
"scripts": {
  "prepublish": "npm run build" 
}

Finally, micro-core gives you a little binary to launch the exported microservice easily:

"scripts": {  
  // …
  "start": "micro-serve -p 3000 dist/"
}
// NOTE: this file belongs in `lib/`! [gist limitation]
import request from 'request-promise';
const URL = 'https://api.bitcoinaverage.com/ticker/global/USD';
export default async function (req, res) {
const price = await request(URL, { json: true });
return `The price is ${price.last} as of ${price.timestamp}`;
}
{
"name": "mva",
"version": "0.0.1",
"description": "a simple example showing off micro + minimum babel settings",
"dependencies": {
"micro-core": "0.3.0",
"request-promise": "3.0.0"
},
"files": [
"dist"
],
"babel": {
"plugins": [
"transform-es2015-modules-commonjs",
"transform-async-to-generator"
]
},
"scripts": {
"start": "micro-serve -p 8080 dist/",
"build": "babel lib --out-dir dist",
"prepublish": "npm run build"
},
"devDependencies": {
"babel-plugin-transform-es2015-modules-commonjs": "6.8.0",
"babel-plugin-transform-async-to-generator": "6.8.0",
"babel-cli": "6.8.0"
}
}
import serve from 'micro-core';
import api from './lib';
serve(api).listen(8080, (err) => {
if (err) throw err;
console.log('Listening on *:8080');
});
@dennerkrans
Copy link

@joshvoll if you run npm run build it will generate the necessary file in the dist folder, and then you just need to write npm run start and you're good to go.

@Obiwarn
Copy link

Obiwarn commented Jul 20, 2017

Fantastic read. Could this be updated to Node v8?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment