Create a gist now

Instantly share code, notes, and snippets.

@rauchg /Readme.md
Last active Mar 13, 2018

What would you like to do?

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');
});
@taoeffect

This comment has been minimized.

Show comment Hide comment
@taoeffect

taoeffect May 18, 2016

What about this "syntax-async-functions" plugin? That's not mentioned in the document?

EDIT: apparently it's not necessary.

taoeffect commented May 18, 2016

What about this "syntax-async-functions" plugin? That's not mentioned in the document?

EDIT: apparently it's not necessary.

@diorahman

This comment has been minimized.

Show comment Hide comment
@diorahman

diorahman Jun 3, 2016

What do you think about having sourcemaps in production?

What do you think about having sourcemaps in production?

@tonyxiao

This comment has been minimized.

Show comment Hide comment
@tonyxiao

tonyxiao Jul 10, 2016

babel-runtime isn't actually the problem, it just reduces a bunch of code duplication. Are you thinking of babel-runtime/regenerator?

babel-runtime isn't actually the problem, it just reduces a bunch of code duplication. Are you thinking of babel-runtime/regenerator?

@leo

This comment has been minimized.

Show comment Hide comment
@leo

leo Jul 28, 2016

@taoeffect Fixed!

leo commented Jul 28, 2016

@taoeffect Fixed!

@joshvoll

This comment has been minimized.

Show comment Hide comment
@joshvoll

joshvoll Nov 23, 2016

This example keep asking me for dist file, not sure what kind error is, can some show me how to runt the little program?

This example keep asking me for dist file, not sure what kind error is, can some show me how to runt the little program?

@joshvoll

This comment has been minimized.

Show comment Hide comment
@joshvoll

joshvoll Nov 23, 2016

Listening on http://localhost:8080
TypeError: fn is not a function

Listening on http://localhost:8080
TypeError: fn is not a function

@dennerkrans

This comment has been minimized.

Show comment Hide comment
@dennerkrans

dennerkrans Nov 28, 2016

@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.

@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

This comment has been minimized.

Show comment Hide comment
@obiwarn

obiwarn Jul 20, 2017

Fantastic read. Could this be updated to Node v8?

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