前書き
Netlify Functionsの入門記事になります。
導入するにあたり色々調べても日本語の記事が少なかったり、Nuxt.jsと組み合わせてどうたらみたいなNetlify Functionsの事に絞られてない記事が多かったので自分用の備忘録も兼ねて。
前提としてJavaScriptチョット書ける、npm使える位の人からを対象とした記事です。
この記事を読むと
・Netlify Functionsの使い方が何となく分かるようになる。
・ローカルでNetlify Functionsのエミュレートが出来るようになる。
・Netlify Functionsを介して外部のAPIとやり取り出来るようになる。
・Netlifyでの環境変数の設定の仕方が分かるようになる。
Netlify Functions is 何
Netlifyが提供しているアドオンの1つ。
**FaaS(Function as a service)**と呼ばれるもので、機能(Functions)を実行できる環境を提供してくれるサービスです。
AWS Lambdaが基盤になっており、実行環境はNode.js 8.10がデフォルトで設定されています(執筆時点)。
10.x系を使いたい場合は、AWS_LAMBDA_JS_RUNTIME
の環境変数にnodejs10.x
を指定すればオーバーライドできます。
(AWS_LAMBDA_JS_RUNTIME
の環境変数で指定できる値は、AWS Lambda runtimeに記載されているものになります。)
Netlifyとリポジトリの連携
何はともあれNetlifyとリポジトリを連携させないと話が始まらないので連携させましょう。
連携させるだけならNetlifyのTOPページから流れに沿って進めるだけで特に難しいところもないので、細かい連携の方法については割愛します。
既にNetlifyと連携しているリポジトリを使うのであれば、Netlify Functionsのために新規でリポジトリを作る必要はありません。
環境構築
Netlifyの設定ファイルを作成する
Netlifyの設定ファイルであるnetlify.tomlファイルをルートディレクトリに作成します。
ここに書く設定はNetlifyの管理ページからでも設定できますが、後述するローカルでのエミュレートにこのファイルが必須になります。
[build]
command = "npm run build"
functions = "dist/api"
command
= Netlifyデプロイ時に実行されるコマンド
functions
= Netlify Functionsのエンドポイント対象ファイルを格納するディレクトリ
ローカルでエミュレートできるようにする
netlify-lambdaを使えばローカルでNetlify Functionsのエミュレートをすることが出来ます。
これが無いと変更→コミット→デプロイ→確認というフローを毎回踏むことになって苦しいです。
後から導入することも出来ますが、Netlifyの設定の仕方によっては色々面倒なことになりかねないので最初に入れておくのがオススメです。
まずはルートディレクトリで
npm init
を実行してpackage.jsonを作成して
npm i netlify-lambda
でインストールしたら、package.jsonに実行用のスクリプトを追記します。
"scripts": {
"dev": "netlify-lambda serve resources/api(ソースが格納されているフォルダ名)",
"build": "netlify-lambda build resources/api(ソースが格納されているフォルダ名)"
}
netlify-lambda serve <folder-name>
で、ローカルで確認できるサーバを立ち上げてくれると同時に、対象としているディレクトリの中身がコンパイルされて、netlify.tomlのfunctions
で指定しているディレクトリに吐き出されます。
デフォルトで使用するポートは9000番ですが、--port
オプションで変更することもできます。
"dev": "netlify-lambda serve resources/api --port 9001"
ここまでで最低限の環境構築は完了です。
Hello Worldが返ってくるAPIを作る
まずはサンプルとしてHello Worldの文字列が返ってくるAPIを作ってみます。
先ほどnetlify-lambda
の対象に設定したディレクトリ(今回の場合resources/api)の中にjsファイルを作成しましょう。
今回はとりあえずhello.jsという名前で作成しました。
このファイル名がエンドポイント名になるので実制作の際は命名に気をつけた方がいいです。
例:hello.js = /.netlify/functions/hello
hello.jsの中身
基本的には公式ドキュメントと全く同じような内容になります。
まずお作法として以下のようにhandler
メソッドをエクスポートする必要があります。
exports.handler = function(event, context, callback) {
// ここに中身の処理を記述
}
とりあえずHello Worldを返すだけなので、中身の処理はこれだけです。
callback
関数の第2引数に、ステータスコードとbodyの情報を渡すだけ。
第1引数はエラーの時用なので今回はnullにしてます。
callback(null, {
statusCode: 200,
body: 'Hello World'
});
ここまで終わったら
npm run dev
でローカルサーバーを立ち上げて、localhost:9000/.netlify/functions/helloにアクセスするとHello Worldが表示されているはずです。
eventパラメータに入っているもの
{
"path": "リクエストのパス",
"httpMethod": "リクエストのメソッド(GETとかPOSTとか)"
"headers": {ヘッダ情報}
"queryStringParameters": {クエリパラメータの情報}
"body": "リクエストの文字列"
"isBase64Encoded": "リクエストがBase64でエンコードされているかどうか"
}
contextパラメータに入っているもの
Netlify Identityを使用している場合にユーザーのコンテキスト情報が返ってきます。(使用していない場合は空の配列)
私自身がNetlify Identityを使用したことがないのであまり詳しいことは分からないです、スミマセン。
asyncを使えば簡潔に書ける
async
を使うことでより簡潔に書くことができます。
(実行環境をNodejs6.10に指定していると使えないので注意)
exports.handler = async () => {
return {
statusCode: 200,
body: 'Hello World',
};
};
コミットして動いているか確認
ここまでの設定が終わったらコミットして本番でも動いているか確認して見ましょう。
デプロイが終わった後、管理ページのFunctionsの中にhello.jsの項目が出来ていたら無事に認識されています。
hello.jsの項目をクリックするとログを見られる画面に遷移します。
Function logのところに実行された履歴や、JS内にconsole.log
を書いていればその内容が表示されます。
EndpointのURLにアクセスして、画面にHello Worldが表示されていれば本番でも問題なく動いています。
Netlify Functionsの中で外部APIを扱う
外部APIを使用する時にAPIのキーをフロント側に持たせたくないというのはあるあるだと思うのですが、Netlifyの環境変数と組み合わせれば幸せになれます。
環境変数の設定(Netlify側)
環境変数の設定はSettings > Build&deploy > Environmentから行えます。
ここでkey
とvalue
を設定しておけば、process.env.KEY
のような感じで環境変数を取得することが出来ます。
環境変数の設定(ローカル側)
セキュアなものでなければnetlify.tomlに以下のように追記することで、ローカルでも環境変数を使用できます。
[build.environment]
KEY="hogefuga"
tomlファイルには数値を書くことができないので、値を””で囲むことを忘れずに。
セキュアな情報を扱いたい場合は**.env**ファイルを使用します。
まずはdotenv-webpack
をインストールして
npm i dotenv-webpack
netlify-lambda
が使用しているwebpackの設定を上書きするためにwebpack.functions.jsファイルを作成します。
中身は以下の通り。
const Dotenv = require('dotenv-webpack')
module.exports = {
plugins: [new Dotenv()],
}
あとは**.env**ファイルを作成して中にキーと値の情報を書いて
KEY=value
dev
コマンドに--config
オプションを追加してwebpackに追加のモジュールを読み込ませるようにします。
"dev": "netlify-lambda serve resources/api --config ./webpack.functions.js",
これでローカルでも環境変数が使えるようになったはずです。
.envファイルをignore設定するのを忘れないように。
axiosのインストール
npm i axios
でaxios
を追加。
あとはJSファイルの中でrequire
してあげれば使えます。
const axios = require('axios');
babelを通してないのでimport
は使えません。
環境変数とaxiosを組み合わせたサンプルとしては以下のような感じになります。
const axios = require('axios');
exports.handler = async () => {
const URL = `https://api.com?key=${process.env.API_KEY}`;
return axios.get(URL)
.then(({ data: data }) => ({
statusCode: 200,
body: JSON.stringify(data)
}))
.catch(e => ({
statusCode: 400,
body: e
}));
};
node-fetchは駄目っぽい
axios
の代わりにnode-fetch
を使ってみようとしたところ、ローカルでは動くもののNetlifyでデプロイ時にコケてしまい駄目でした。(netlify-lambda
を使っていない状態なら大丈夫だったので、コンパイル時に何か問題が起こってる?)
色々調べ回っていた時にどこかのIssueで、node-fetchじゃなくてaxiosの使用を推奨しています。
みたいな事を書いているのを見かけたのでそういう事なのかなと。
#おしまい
ざっくりとした説明でしたが以上になります。
Netlifyをお使いの方はぜひお試しください。