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:
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:
module.exports = (req, res) => { const { name = 'World' } = req.query res.send(`Hello ${name}!`) }
An example serverless Node.js function.
@now/node
Builder also supports asynchronous functions, an example of which can be found in the Request and Response Objects section.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.
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.
Helpers
In addition to the standard Node.js request and response methods, we provide a set of helper properties and methods to make it even easier for you to build a new lambda function:
method | description | object |
---|---|---|
req.query | An object containing the request's query string, or {} if the request does not have a query string. | request |
req.cookies | An object containing the cookies sent by the request, or {} if the request contains no cookies. | request |
req.body | An object containing the body sent by the request, or null if no body is sent. | request |
res.status(code) | A function to set the status code sent with the response where code must be a valid HTTP status code. Returns res for chaining. | response |
res.send(body) | A function to set the content of the response where body can be a string , an object or a Buffer . | response |
res.json(obj) | A function to send a JSON response where obj is the JSON object to send. | response |
The following lambda example showcases the use of req.query
, req.cookies
and req.body
helpers:
module.exports = (req, res) => { let who = 'anonymous' if (req.body && req.body.who) { who = req.body.who } else if (req.query.who) { who = req.query.who } else if (req.cookies.who) { who = req.cookies.who } res.status(200).send(`hi ${who}, what's up?`) }
Example Node.js lambda using the req.query
, req.cookies
and req.body
helpers. It returns greetings for the user specified using req.send()
.
helpers
to false
in the configuration of the builder. If you opt-out, request objects will be replaced by the standard HTTP request and response.{
"builds": [
{ "src": "my-file.js", "use": "@now/node", "config": { "helpers": "false" } }
]
}
You can opt-out of helpers by setting helpers
to false
in the configuration.
req.body
We populate the req.body
property on the request object with a parsed version of the content sent with the request when it is possible.
We follow a set of rules on the Content-type
header sent by the request to do so:
Content-Type header | Value of req.body |
---|---|
No header | undefined |
application/json | An object representing the parsed JSON sent by the request. |
application/x-www-form-urlencoded | An object representing the parsed data sent by with the request. |
text/plain | A string containing the text sent by the request. |
application/octet-stream | A Buffer containing the data sent by the request. |
With the req.body
helper, you can build applications without extra dependencies or having to parse the content of the request manually. The following example inspects req.body
, if it is 'ping', it will return 'pong'.
module.exports = (req, res) => { if (typeof req.body !== 'string') { return res.status(400).text('Invalid request') } if (req.body !== 'ping') { return res.status(400).text('The value expected is `ping`') } res.status(200).send('pong') }
An example Node.js lambda using the req.body
helper that returns pong
when you send ping
.
Typescript support
We provide types for the request and response objects.
To install these types, use the following command:
yarn add @now/node --dev
Or, if you're using npm
:
npm install @now/node --save-dev
Once the types have been installed, import NowRequest
and NowResponse
from @now/node
, to type the request and response objects:
import { NowRequest, NowResponse } from '@now/node' export default function(req: NowRequest, res: NowResponse) { const { name = 'World' } = req.query res.send(`Hello ${name}!`) }
An example "Hello World" Typescript lambda using the req.query
helper.
Async support
We support asynchronous functions out-of-the-box.
In this example, we use the package asciify-image
to create ascii art from a person's avatar on github. First, we need to install the package:
yarn add asciify-image
In our code, we export an asynchronous function and we take advantage of the helpers.
const asciify = require('asciify-image') module.exports = async (req, res) => { if (!req.query.username) { return res.status(400).send('username is missing from query parameters') } const avatarUrl = `https://github.com/${req.query.username}.png` const opts = { fit: 'box', width: 40, height: 40 } const asciified = await asciify(avatarUrl, opts) return res.status(200).send(asciified) }
An example showcasing the use of an asynchronous function.
Deploying with Static Content
You can upload static content alongside 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 on including static files in your project, 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, you should read the documentation for the @now/node-server
Builder, although this is not recommended.
@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
.
Alternatively, define NPM_RC
as a build environment variable with the contents of ~/.npmrc
.
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.
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.send(`
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 default Node.js version used is 8.10.x.
The version can be changed to 10.x by defining engines in package.json
:
{
"name": "my-app",
"engines": {
"node": "10.x"
}
}