If your project has source files that need to be built requiring a different structure than Now provides by default, you can use Builders with advanced configuration to achieve that structure.
Builders can be used with Now by creating a now.json
file in a project and then using a builds
property within that configuration:
{
"builds": [
{ "src": "*.html", "use": "@now/static" },
{ "src": "date.js", "use": "@now/node" }
]
}
The builds
property is an array of objects where each object is a build step, including a src
and a use
property, at least.
The Builder will receive a list of files based on the src
property's glob value.
src
property is a glob. In the above example, this will only use the Static Builder for the HTML files in the root directory. If you need it to be used throughout subdirectories, you need the appropriate glob syntax: **/*.html
.The use
property of a build step can contain the name of a Builder module published to npm. For example, the following list contains the Official Builders and their module names to use.
Builder | Builder Module |
---|---|
Static | @now/static |
Static Build | @now/static-build |
Node.js | @now/node |
Next.js | @now/next |
Go | @now/go |
Python | @now/python |
Ruby | @now/ruby |
Since Builders are published to npm, the use
statement in your now.json
file uses a similar syntax to npm install
, meaning that versioning can be used by tagging the builders, like for example:
{
"builds": [{ "src": "api/**/*.js", "use": "@now/node@0.12.3" }]
}
The following is a list of community maintained Builders.
Builder | Builder Module | Docs |
---|---|---|
PHP | now-php | https://github.com/juicyfx/now-php |
Rust | now-rust | https://github.com/mike-engel/now-rust |
You can configure your own build step using the Static Builds Builder by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "package.json", "use": "@now/static-build" }]
}
The entry point for src
must be a package.json
file with a build
script that, when executed, compiles the built application into a public
directory.
If you want to configure a directory other than public
for your build output, you can pass an optional distDir
option in the builder's config:
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@now/static-build",
"config": { "distDir": "www" }
}
]
}
Using a file with a .sh
file extension as an entry point for the @now/static-build
Builder allows you to define build instructions in a shell file.
For example, creating a shell file, with the name build.sh
, with the following contents, will install and build a Hugo project:
curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.55.6/hugo_0.55.6_Linux-64bit.tar.gz
tar -xzf hugo_0.55.6_Linux-64bit.tar.gz
./hugo
For depencency installation with shell file entry points, yum
is available.
To install private npm modules, define NPM_TOKEN
as a build environment variable in a now.json
file.
Alternatively, define NPM_RC
as a build environment variable with the contents of ~/.npmrc
.
You can configure your own build step using the Node.js Builder, to compile Node.js source files into Serverless Functions, by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "index.js", "use": "@now/node" }]
}
The entry point for src
must be a glob matching .js
or .ts
files that export a default function. For more information on using this Builder, see the Node.js Builder section.
Within a now.json
configuration file at your project's root, use the following build step with config to disable helpers.
{
"builds": [
{
"src": "my-file.js",
"use": "@now/node",
"config": { "helpers": "false" }
}
]
}
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
.
You can run build tasks by creating a now-build
script within a package.json
file at the entry point's level or higher. For example:
{
"scripts": {
"now-build": "node ./build.js"
}
}
Along with 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!')
})
And a .js
file for the built Serverless Functions, index.js
inside the /api
directory:
const BuiltTime = require('./built-time')
module.exports = (req, res) => {
res.setHeader('content-type', 'text/plain')
res.send(`
This Serverless Function was built at ${new Date(BuiltTime)}.
The current time is ${new Date()}
`)
}
A Node.js Builder entrypoint can contain one of the following to retain legacy serverful behavior:
module.exports = http.createServer((req, res) => { res.end('hello') })
.http.createServer((req, res) => { res.end('hello') }).listen(3000)
.The Node.js Builder provides a config.awsLambdaHandler
to opt into the AWS Lambda API. This is useful if you have existing functions you wish to deploy to ZEIT Now but do not want to change the API.
exports.handler = async function() {
return {
statusCode: 200,
headers: {},
body: 'Hello world'
}
}
You can deploy this function with the following now.json
configuration file:
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "@now/node",
"config": { "awsLambdaHandler": "index.handler" }
}
]
The awsLambdaHandler
uses the same syntax as AWS Handler which is the file name and the exported function name.
You can configure your own build step using the Next.js Builder, to compile Next.js source files into Serverless Functions, by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "package.json", "use": "@now/next" }]
}
The entry point of this Builder is a package.json
file with Next.js 9 or newer defined in dependencies
. For more information on using this Builder, see the Next.js Builder section.
For more information on this, see the Next.js documentation.
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
.
To support environment variables, Next.js inlines the provided values into the JavaScript bundle at build.
You can add the env
key to the next.config.js
file:
module.exports = {
env: {
customKey: process.env.customKey,
mySecret: process.env.mySecret
}
}
Then, expose the build env in your now.json
:
{
...
"build": {
"env": {
"customKey": "value",
"mySecret": "@my-secret-name"
}
}
}
This will allow you to use process.env.customKey
and process.env.mySecret
in your code.
You can configure your own build step using the Go Builder, to compile Go source files into Serverless Functions, by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "index.go", "use": "@now/go" }]
}
The entry point of this Builder is a global matching .go
files that export a function that implements the http.HandlerFunc
signature. For more information on using this Builder, see the Go Builder section.
To install private packages with go get
, define GIT_CREDENTIALS
as a build environment variable in now.json
.
All major Git providers are supported including GitHub, GitLab, Bitbucket, as well as a self-hosted Git server.
With GitHub, you will need to create a personal token with permission to access your private repository.
{
"build": {
"env": {
"GIT_CREDENTIALS": "https://username:token@github.com"
}
}
}
You can configure your own build step using the Python Builder, to compile Python source files into Serverless Functions, by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "index.py", "use": "@now/python" }]
}
The entry point of this Builder is a glob matching .py
source files with one of the following variables defined:
handler
that inherits from the BaseHTTPRequestHandler
class.app
that exposes a WSGI or ASGI Application.The Web Server Gateway Interface (WSGI) is a calling convention for web servers to forward requests to web applications written in Python. You can use WSGI with frameworks such as Flask or Django.
Instead of defining a handler
, define an app
variable in your Python file, when using now.json
config. For example, define a index.py
file inside your project as follows:
from flask import Flask, Response
app = Flask(__name__)
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
return Response("<h1>Flask on Now</h1><p>You visited: /%s</p>" % (path), mimetype="text/html")
Inside requirements.txt
define:
flask==1.0.2
The Asynchronous Server Gateway Interface (ASGI) is a calling convention for web servers to forward requests to asynchronous web applications written in Python. You can use ASGI with frameworks such as Sanic.
Instead of defining a handler
, define an app
variable in your Python file.
For example, define a index.py
file inside a folder as follows:
from sanic import Sanic
from sanic.response import json
app = Sanic()
@app.route('/')
@app.route('/<path:path>')
async def index(request, path=""):
return json({'hello': path})
Inside requirements.txt
define:
sanic==19.6.0
You can configure your own build step using the Ruby Builder, to compile Ruby source files into Serverless Functions, by providing configuration like the following, inside of a now.json
file:
{
"builds": [{ "src": "index.rb", "use": "@now/ruby" }]
}
The entry point of this Builder is a glob matching .rb
or .ru
(for Rack) source files with one of the following variables defined:
Handler
proc that matches the do |req, res|
signature.Handler
class that inherits from the WEBrick::HTTPServlet::AbstractServlet
class.For more information on using this Builder, see the Ruby Builder section.
Alternatively, a .ru
Rack config file will serve the Ruby application it contains.
Many Ruby frameworks interface with Rack for forwarding HTTP requests to web applications written in Ruby. You can use Rack with frameworks such as Sinatra or Rails.
Instead of defining a handler, write the application as usual, like this Sinatra application:
require 'sinatra'
get '/*' do
'Hello world'
end
Inside Gemfile
define:
source "https://rubygems.org"
gem "sinatra", "~> 2.0"
gem "rack", "~> 2.0"
Add a Rack config file at index.ru
to start the application:
require './app'
run Sinatra::Application
Extending the feature-set of a ZEIT Now deployment is as simple as creating a Builder that takes a list of files and outputs either static files or dynamic Serverless Functions.
A full API reference is available to help with creating Builders.
A builder can retain an archive of up to 100mb
of the filesystem at build
time. The cache key is generated as a combination of:
api/users/index.go
).@now/go@0.0.1
).The cache will be invalidated if any of those items changes. The user can bypass the cache by running now -f
.
Most Builders use static analysis to determine which source files should be included in the Serverless Function output based on the build src
input. Any unused code or assets is ignored to ensure your Serverless Function is as small as possible.
For example, the Node Builder looks at calls to require()
or fs.readFile()
in order to determine which files to include automatically.
// index.js
const { readFileSync } = require('fs');
const { join } = require('path');
const file = readFileSync(join(__dirname, 'config', 'ci.yml'), 'utf8');
In some cases, you may wish to include templates or views that are not able to be statically analyzed. Builders provide a configuration for includeFiles
that accepts an array of globs that will always be included in the Serverless Functions output.
{
"builds": [
{
"src": "index.js",
"use": "@now/node",
"config": {
"includeFiles": [
"templates/**",
"views/**"
]
}
}
]
}