Vercel を素振りしてみたメモ

Now という PaaS(静的サイトしかできないものだと思っていたけど動的もできたらしい)がいつのまにか Vercel という名前に変わった? ようなので試してみました。

ZEIT is now Vercel – Vercel

イントロダクションだと Github などのコードリポジトリからデプロイしたり、Vercel の examples からデプロイしたりでしたが、ひとまず CLI から最小構成でデプロイしてみます。

最小構成のデプロイ

Vercel の CLI をインストールします。

Download Vercel – Vercel

sudo npm i -g vercel

CLI で Vercel ログインします。

vercel login ore-no-email@example.com

メールが届くのでそのメールに記載されたリンクを踏みます。ログインに成功すると ~/.local/share/com.vercel.cli/auth.json に認証用のトークンが保存されます。

public ディレクトリを作って適当なファイルを置きます。Vercel はデフォで public を公開ディレクトリにします。

mkdir -p public
echo 'hello vercel' > public/index.html

vercel コマンドでデプロイします。vercel deploy でも同じです。

vercel

プロンプトでいろいろ表示されるので Enter を連打します。プロンプト中に Production: https://... のように表示された URL を開くとファイルの内容が表示されます。

Vercel の Web のダッシュボードを見てみると自動的にプロジェクトが作成されています。また、ローカルの .vercel/project.json にプロジェクトとの関連付けのための情報が記録されています。

Production と Preview

Deployments - Vercel Documentation

Vercel のデプロイメントには Preview と Production の2種類があります。

vercel コマンドでデプロイすると初回だけは Production と Preview の両方にデプロイされますが、2回目以降は Preview のみにデプロイされます。

2回目以降の Production へのデプロイは vercel --prod でできます。

デプロイメントのドメインは $PROJECT-$UID.vercel.app のような形式です。

Production のデプロイメントでは $UID には意味のある英単語がランダムで入るようで、プロジェクトが作成されたときに自動生成されます。これは後で変更することも可能で、任意のドメインが指定できます。.vercel.app のサブドメイン以外にも変更可能で、その場合は後述のカスタムドメインになります。

Preview のデプロイメントでは $UID には、vercel.json、ユーザーID(チームID)、ファイルシステムの内容、を元に生成されます。同じ $UID ならデプロイはスキップされます。

つまり、同じソースツリーからは何度デプロイしても Preview デプロイメントは1つしか作られません。

なお、Preview デプロイメントには x-robots-tag: noindex レスポンスヘッダが含まれているので Google などの検索エンジンでインデックス化されません。また、有料アカウントであれば Preview デプロイメントにパスワードや Vercel ログインなどのアクセス制御を設けることができます。

ビルド

Build Step - Vercel Documentation

package.json でデプロイ時のビルドコマンドを指定できます。これは Vercel のサーバ上で実行されます。

{
    "scripts": {
      "build": "date > public/index2.html"
    }
}

カスタムドメイン

Custom Domains - Vercel Documentation

カスタムドメインも使えます。カスタムドメインを有効にすると自動的に Let's Encrypt の証明書も発行されるので自分で証明書を運用する必要はありません。

カスタムドメインの有効化には、よくある CNAME レコードを使う方法と、ドメインのネームサーバを Vercel のネームサーバに変更する方法があります。

ドメインのネームサーバを Vercel のネームサーバに変更した場合、Vercel のプロジェクトのカスタムドメインのための CNAME とは無関係なゾーン情報も管理できるようになります。要するにフルマネージドのDNSコンテンツサーバとしても普通に使えるようです。

Serverless Function

Serverless Functions - Vercel Documentation

Serverless Function でバックエンドもデプロイできます。以下の言語がサポートされています。

  • Node.js
  • Go
  • Python
  • Ruby

TypeScript はデプロイ時に自動で js にビルドされるためローカルでビルドは不要です。

コードはプロジェクトの api ディレクトリにバックエンド言語ごとの適切な拡張子をつけて保存します。デフォだとこのディレクトリのコードのみが Serverless Function として認識されます。

mkdir -p api
code api/hello.ts
import { NowRequest, NowResponse } from '@vercel/node'

export default (req: NowRequest, res: NowResponse) => {
    res.json({ msg: 'hello vercel' })
}

ファイル名がそのまま URL になります。/api/hello のようなパスの URL を開くと↑のコードの結果が得られます。

[name].ts ファイル名にするとパスパラメータとして扱えます。

mkdir -p api/name
code 'api/name/[name].ts'
import { NowRequest, NowResponse } from '@vercel/node'

export default (req: NowRequest, res: NowResponse) => {
    res.json({ msg: `my name of ${req.query.name}` })
}

/api/name/oreore のようなパスの URL でアクセスすると {"msg":"my name of oreore"} などと結果が返ってきます。

Local Development

Serverless Functions - Vercel Documentation

vercel dev で Serverless Function も含んだ内容をローカルで実行できます。コードを編集すると自動でビルド&サーバのリロードも行われるようです。

package.json で scripts.dev を指定すれば独自の Web サーバを使うこともできます。このときリッスンすべきポートが $PORT で入ってくるのでそのポートでリッスンする必要があります。例えば次のように PHP のビルドインウェブサーバを使ったりできます。

{
    "scripts": {
        "dev": "php -S 0.0.0.0:$PORT -t public"
    }
}

見たところ scripts.dev で指定した $PORT には 50000 を超えるような空いている適当なポートが指定され、Vercel の 3000 とかでリッスンしたサーバが Serverless Function へのリクエスト以外をそのポートへ転送しているようです。

上記の PHP を指定する例は全く意味がありませんが、通常は next.js などのフレームワークが dev server を提供している場合にそのサーバへプロキシするために使用されます。

環境変数

Build Step - Vercel Documentation

環境変数を追加・削除できます。環境変数はビルドの実行時と Serverless Function の実行時に利用できます。

環境変数は Production、Preview、Development でそれぞれ別々に設定します。

echo 123 | vercel env add AAA production
echo 456 | vercel env add AAA preview
echo 789 | vercel env add AAA development

Development は vercel dev コマンドのローカル開発サーバ用のものです。vercel env add コマンドで設定しただけでは有効にならず、vercel env pull コマンドで .env に出力する必要があります。それなら Vercel で監視しなくてもローカルの .env に直接書けば良い気もしますが・・・

vercel -e でデプロイ時にも環境編が指定できます。この場合は特定のデプロイメントのみで有効な環境変数になります。

vercel -e AAA=123

.vercelignore

デフォルトで下記のファイルはデプロイから除外されます。

Build Step - Vercel Documentation

これら以外に除外したいファイルは .vercelignore で指定できます。

vercel.json

vercel.json で構成がいろいろ設定できます。functions routes rewrites あたりが特に使いそうでしょうか。

Configuration - Vercel

例えば次のようにすれば /app/ の中のリクエストをすべて /api/index にルーティングすることができます。

{
    "rewrites": [
        { "source": "/app/(.*)", "destination": "/api/index" }
    ]
}

注意が必要そうな点として・・Serverless Function に含まれるファイルはソースファイルの静的解析によって決定されます。

Official Vercel Runtimes - Vercel

ので、静的解析で追いきれないファイルがあるときは vercel.json で次のように指定する必要があります。

{
  "functions": {
    "api/test.js": {
      "includeFiles": "templates/**"
    }
  }
}

この指定は .vercelignore によるデプロイメントからの除外とは別のものです。まず .vercelignore でデプロイメントに含まれるファイルが決定され、さらに Serverless Function ごとに含まれるファイルが vercel.json の指定で決定されます。

デプロイメントに含まれているファイルは Vercel のダッシュボードから閲覧できますが、そこに含まれているからと言って Serverless Function に含まれているとは限らないので注意が必要です。

Serverless Function に含まれているファイルを確認する方法は・・無さそう?

さいごに

中身は AWS で CloudFront やら Lambda@Edge やら API Gateway やらが駆使されているようですが、この構成がさっくり作れるのは非常に便利そうです。

一方、本気で作り込むなら AWS を直接使えば良いんじゃない? と言う気もします。

個人的なちょっとしたツールとかを置くのには良いかもしれません。