JAMStackなアプリを開発するには動的コンテンツの表示も可能にしなくてはならない。そのためにはマイクロAPIからデータを取得してくる必要がある。Netlifyはその機能を実現するためにFunctionsを機能として備えている。また、NetlifyはサードパーティのライブラリをインストールすることなくSplit TestingでA/Bテストを行う事ができる。しかもGitのブランチレベルでのトラフィックの振り分けが可能だ。
Netlifyのチュートリアルについて知りたければ以前のNuxt.js (TypeScript) on Netlifyの良さを広めたいの記事を参照してほしい。
目次
- Netlify Functionsとは
- Netlify Split Testingとは
- Nuxt TypeScriptのサンプルプロジェクトをClone
- netlify-lambdaのインストール
- FunctionsをTypeScriptで書く
- Nuxt.jsからFunctionsの呼び出し
- Split TestingでA/Bテストをやってみる
- 最後に
Netlify Functionsとは
裏はAWS Lambdaになっているようだが、我々が特にAWSを意識する事はない。価格は公式から引用させてもらうと
All Netlify sites include 125,000 function requests per month, and 100 hours of run time per month. Above that, billing scales with your usage.
125,000リクエスト/月、実行時間が100時間まで無料らしい。あとは従量課金制だ。個人的にAWS LambdaやCloud FunctionsはGB秒という確保するメモリと実行時間を合わせた単位で課金されるので、あまり直感的ではないが、Netlify Functionsはリクエスト数と実行時間のみで課金されるようだ。
Netlify Split Testingとは
段階的ロールアウトやA/B TestingなどUIから簡単に設定できる機能。まだBETA(Feb 5 2019時点)だが、個人的に今回一番推したい機能。
Nuxt TypeScriptのサンプルプロジェクトをClone
既にサンプルは用意したので、以下のレポジトリからCloneするかForkして、Github上にプロジェクトを作っておく。masterではなく、functionsのブランチを今回利用するので注意。
git clone https://github.com/tamanyan/nuxt-ts-netlify.git <project-name>
cd <project-name>
yarn or npm install
netlify-lambdaのインストール
関数の実行やビルドなどしたい場合はnetlify/netlify-lambdaが便利。TypeScriptのビルドなども対応しているようだ。サンプルプロジェクトでは全て設定が完了しているので特に何もする必要はない。念の為netlify.toml
の設定部分に関してのみ説明しておくと、command
はビルドコマンド、functions
にLambda関数を置いておくようにする。publish
は公開ディレクトリ。
# example netlify.toml
[build]
command = "yarn generate" # generate cmd
functions = ".lambda" # netlify-lambda reads this
publish = "dist" # The directory you want to publish
FunctionsをTypeScriptで書く
functions
のhello.ts
にLambda関数を書く、ビルドすると.lambda
に出力されるようになっている。
functions/hello.ts
import { Handler, Context, Callback, APIGatewayEvent } from 'aws-lambda'
interface HelloResponse {
statusCode: number
body: string
}
export const handler: Handler = (
event: APIGatewayEvent,
context: Context,
callback: Callback
) => {
const params = event.queryStringParameters
const response: HelloResponse = {
statusCode: 200,
body: JSON.stringify({
msg: `Hello world ${Math.floor(Math.random() * 10)}`,
requestId: context.awsRequestId || "dummy",
params
})
}
callback(undefined, response)
}
Nuxt.jsからFunctionsの呼び出し
ローカルでも呼び出せるようにaxios
とproxy
の設定をしておく。Nuxt.jsはポート3000で立ち上がるが、ローカルでnetlify-lambdaを使って関数を立ち上げると9000で起動するので、proxyを通しておくと便利。
nuxt.config.ts
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
/*
** Axios module configuration
*/
axios: {
proxy: true // Can be also an object with default options
},
proxy: {
'/.netlify/': { target: 'http://localhost:9000/' }
},
ここでは、Functionsが呼び出せるかどうかだけを確かめるためにmounted
で直接APIを叩いて関数を呼び出す。
src/pages/index.vue
<template>
<section class="container">
<div>
<logo />
<h1 class="title">
Nuxt TypeScript Sample
</h1>
<h2 class="subtitle">
{{ subtitle }}
</h2>
<div class="links">
<a
href="https://nuxtjs.org/"
target="_blank"
class="button--green"
>Documentation</a>
<a
href="https://github.com/nuxt/nuxt.js"
target="_blank"
class="button--grey"
>GitHub</a>
</div>
</div>
</section>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import Logo from '../components/Logo.vue'
@Component({
components: {
Logo,
}
})
export default class Index extends Vue {
subtitle: string = 'Nuxt TypeScript Project!'
async mounted() {
// Call Netlify Functions
const response = await this.$axios.$get('./.netlify/functions/hello')
// Set subtitle from message
this.subtitle = response.msg
}
}
</script>
元々はNuxt TypeScript Project!
が表示されていたが、APIのレスポンスからmsg
を取得してHello World <number> になっている。
Split TestingでA/Bテストをやってみる
masterとfunctionsの両方のブランチを使ってA/Bテストをやってみる。使い方は直感的で迷う事はない。ここではmasterに10%、functionsに90%振り分けてみる。
細かい部分として、今訪問者がどのブランチで出力されているのかを環境変数から取得することができる。これらはGoogle Analyticsなどの計測に使える。
nuxt.config.ts
export default {
env: {
BRANCH: process.env.BRANCH || 'undefined'
}
src/pages/index.vue
export default class Index extends Vue {
subtitle: string = 'Nuxt TypeScript Project!'
async mounted() {
// Call Netlify Functions
const response = await this.$axios.$get('./.netlify/functions/hello')
// Set subtitle from message
this.subtitle = response.msg
// Show current branch
console.log('Your branch is', process.env.BRANCH)
// -> master or functions
}
}
最後に
NetlifyのFunctionsとSplit Testingを使って、A/Bテストまで試してみた。個人的な感想として、NetlifyはCDNにいろいろとサービスがくっついただけで、自動ビルド・デプロイ、Functions、Split Testingを使う程度ではNetlifyへのサービスロックインにはなりにくい。Netlify Functionsは裏がAWS Lambdaで移植性は高い(AWS Lambdaへのロックインはしょうがない)。A/Bテストに関してはアプリケーションのソースコードレイヤーのレベルではないため問題ない。安い(or 無料)だし、悩むくらいなら始めてみようぜといえるサービスになっている。