Node.js Builder (@now/node)

Status: Stable

The @now/node Builder takes an entrypoint of a Node.js function, builds its dependencies (if any) and bundles them into a Lambda.

When to Use It

This Builder is the recommended way to introduce any Node.js-based dynamic request handling into your codebases.

It can be used directly (as a single file, like my-function.js), or you can define an index.js file inside a directory.

How to Use It

For this example, we will create a hello endpoint that we want to access as my-deployment.url/api/hello.

Let's create our project structure:

mkdir -p my-node-project/api/hellocd my-node-project/api/hello

Inside my-node-project > api > hello we will create an index.js file.

The index.js file exports a Node.js function that takes in the standard Node.js request and response objects:

const { parse } = require('url')

module.exports = (req, res) => {
  const { query } = parse(req.url, true)
  const { name = 'World' } = query
  res.end(`Hello ${name}!`)
}

An example serverless Node.js function.

The only step left is to define a build that will take this directory's entrypoint (index.js), build it and turn it into a lambda:

{
  "version": 2,
  "builds": [{ "src": "api/hello/index.js", "use": "@now/node" }]
}

An example now.json configuration using the @now/node builder.

Our resulting deployment is here: https://my-node-project-5gkn6kqfy.now.sh/

The example deployment above is open-source and you can view the code for it here: https://my-node-project-5gkn6kqfy.now.sh/_src

You can pass query parameters to make the name change:

The lambda using the name query parameter to change the text using Node.js.

Deploying with Static Content

You can upload static content along side your Node.js application by using [the @now/static builder].

For example, if you have a static directory and an index.js like the one from the example above, you can serve that directory statically by extending your now.json configuration:

{
  "version": 2,
  "builds": [
    { "src": "api/hello/index.js", "use": "@now/node" },
    { "src": "static/**", "use": "@now/static" }
  ]
}

Deploying a serverless Node.js function along with static files.

For more information, read the documentation for @now/static:

Technical Details

Entrypoint

The entrypoint of this Builder is always a JavaScript file that exposes a function. If you want to expose a server, look into @now/node-server, although that is not recommended.

Note: @now/node will automatically detect a `package.json` file to install dependencies at the entrypoint level or higher.

Dependencies Installation

The installation algorithm of dependencies works as follows:

  • If a package-lock.json is present, npm install is used
  • Otherwise, yarn is used.

Private npm modules

To install private npm modules, define NPM_TOKEN as a build environment variable in now.json.

Build Step

You can run build tasks by creating a now-build script within a package.json file at the entrypoint's level or higher.

An example package.json with a now-build script:
{
  "scripts": {
    "now-build": "node ./build.js"
  }
}
An example build script, named build.js:
const fs = require('fs');
  fs.writeFile(
  'built-time.js',
  `module.exports = "${new Date()}"`,
  (err) => {
    if (err) throw err
    console.log('Build time file created successfully!')
  }
)
An example entrypoint file for the built lambda, index.js:
const BuiltTime = require('./built-time')

module.exports = (req, res) => {
  res.setHeader('content-type', 'text/plain');
  res.end(`
    This Lambda was built at ${new Date(BuiltTime)}.
    The current time is ${new Date()}
  `)
}
To tie it all together, a now.json file:
{
  "version": 2,
  "builds": [
    { "src": "index.js", "use": "@now/node" }
  ]
}

The resulting lambda contains both the build and current time: https://build-time-pq6g1255e.now.sh/

Node.js Version

The Node.js version used is the v8.10.

Request and Response Objects

For each invocation of a Node.js lambda, two objects, request and response, are passed to the function. These objects are the standard HTTP request and response objects given and used by Node.js.

With many Node.js-based frameworks like Express also frequently dealing with these HTTP request and response objects, you may be able to use them in your Node.js lambda. The following lambda example, using Express, accepts a JSON body in the POST request, and returns a stringified version of it.

Example Node.js lambda using express and body-parser
'use strict'

const express = require('express')
const bodyParser = require('body-parser')

const app = express()
module.exports = app

app.use(bodyParser.json())

app.post('*', (req, res) => {
  if (req.body == null) {
    return res.status(400).send({ error: 'no JSON object in the request' })
  }

  res.set('Content-Type', 'application/json')
  res.status(200).send(JSON.stringify(req.body, null, 4))
})

app.all('*', (req, res) => {
  res.status(405).send({ error: 'only POST requests are accepted' })
})

For more information, see the following examples: Express and Twitter Dreamify with Express.

Maximum Lambda Bundle Size

To help keep cold boot times low, the maximum output bundle size for a Node.js output lambda is, by default, 5mb. This limit is extendable up to 50mb.

Example maxLambdaSize configuration:
{
  "builds": [
    { "src": "*.js", "use": "@now/node", "config": { "maxLambdaSize": "10mb" } }
  ]
}