Now という PaaS(静的サイトしかできないものだと思っていたけど動的もできたらしい)がいつのまにか Vercel という名前に変わった? ようなので試してみました。
イントロダクションだと Github などのコードリポジトリからデプロイしたり、Vercel の examples からデプロイしたりでしたが、ひとまず CLI から最小構成でデプロイしてみます。
最小構成のデプロイ
Vercel の CLI をインストールします。
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
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 ログインなどのアクセス制御を設けることができます。
ビルド
package.json でデプロイ時のビルドコマンドを指定できます。これは Vercel のサーバ上で実行されます。
{ "scripts": { "build": "date > public/index2.html" } }
カスタムドメイン
カスタムドメインも使えます。カスタムドメインを有効にすると自動的に Let's Encrypt の証明書も発行されるので自分で証明書を運用する必要はありません。
カスタムドメインの有効化には、よくある CNAME レコードを使う方法と、ドメインのネームサーバを Vercel のネームサーバに変更する方法があります。
ドメインのネームサーバを Vercel のネームサーバに変更した場合、Vercel のプロジェクトのカスタムドメインのための CNAME とは無関係なゾーン情報も管理できるようになります。要するにフルマネージドのDNSコンテンツサーバとしても普通に使えるようです。
Serverless Function
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
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 を提供している場合にそのサーバへプロキシするために使用されます。
環境変数
環境変数を追加・削除できます。環境変数はビルドの実行時と 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
デフォルトで下記のファイルはデプロイから除外されます。
これら以外に除外したいファイルは .vercelignore
で指定できます。
vercel.json
vercel.json で構成がいろいろ設定できます。functions routes rewrites あたりが特に使いそうでしょうか。
例えば次のようにすれば /app/
の中のリクエストをすべて /api/index
にルーティングすることができます。
{ "rewrites": [ { "source": "/app/(.*)", "destination": "/api/index" } ] }
注意が必要そうな点として・・Serverless Function に含まれるファイルはソースファイルの静的解析によって決定されます。
ので、静的解析で追いきれないファイルがあるときは 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 を直接使えば良いんじゃない? と言う気もします。
個人的なちょっとしたツールとかを置くのには良いかもしれません。