今回達成すること
このチャプターで実装する「ブログ検索機能」には、Netlify Functionsを使用します。
この記事では、Nerlity Functionsのインストールとセットアップ、そしてクエリを返すテスト関数を作成し、ローカルサーバーで実行します。
ブログ検索機能を実装するには?
検索機能を実行するには、ユーザーが入力した検索キーワードを持って、Contentful APIへリクエストを行います。
NuxtからContentful APIへリクエストを行うと、フロントからリクエストを行う必要があり、API KeyをJavaScriptに登録しなければなりません。
JavaScriptにAPI Keyを登録すると、ここでお伝えした通りKeyが漏洩します。
API Keyの漏洩を防ぐ検索機能の実装方法
API Keyの漏洩を防ぐには、
- フロントで入力された検索キーワードを
axios
モジュールでNetlify Functionsに渡し、- サーバーサイドからContentful APIへリクエストを行う必要があります。
上記の実装で、JavaScriptにAPI Keyを登録しなくてもAPIリクエストを行うことができます。
Netlify Functionsとは?
Netlify Functionsとは、JavaScriptの関数によってサーバーを操作する、Netlifyが用意している機能です。2022年2月現在、Go言語も使用可能です。
Documents: Functions overview | Netlify Docs
料金
Netlify Functionsの料金はリクエスト数によって課金されます。
無料プランでは、月リクエスト数が125,000回まで無料、超過した場合は$25が課金されます。
Starter(無料) | Pro($19/月) | Business($99/月) | |
---|---|---|---|
Serverless FunctionsInvocations | 125k per site /month ($25+ when exceeded) |
125k per site /month ($25+ when exceeded) |
Unlimited |
最新の料金は下記URLよりご確認ください。
前提条件
Netlify Functionsを実行するには、netlify
コマンドが使用できる環境が必要です。
上記コマンドを使用するには、netlify-cli
をインストールします。
% yarn add --dev netlify-cli
既にインストール済みの方は実行しないでください。
インストール
Netlify Functionsを使用するには、@netlify/functions
モジュールをインストールします。
% yarn add @netlify/functions
下記で手順に沿ってインストールするので、まだ実行しないでください。
Functionsプロジェクトの作成
Netlifyが用意しているfunctions:create
コマンドでFunctionsを操作するプロジェクトを作成することができます。
作成されるプロジェクトにJavaScriptの関数を記述します。
% yarn netlify functions:create
下記で手順に沿って作成するので、まだ実行しないでください。
Functionsプロジェクトの置き場所
今回は「netlify」ディレクトリを作成し、その中でNetlify Functionsのセットアップを行います。
「netlify」ディレクトリは、Functionsを扱うための別アプリだとお考えください。
Netlify Functionsのインストールとセットアップ
作業に入る前にブランチを切っておきましょう。
% git checkout -b 20220211_netlify_functions
% git branch
* 20220211_netlify_functions
Functionsを扱う「netlify」ディレクトリを作成し、その直下に
% mkdir netlify && touch $_/package.json
package.jsonのセットアップ
作成した
netlify/package.json
{
"name": "<アプリ名>_functions",
"version": "1.0.0",
"private": true,
"scripts": {},
"dependencies": {},
"devDependencies": {}
}
"<アプリ名>_functions"
... Nuxtルートディレクトリ直下にあるpackage.json のname
の値をアプリ名に入力する。
@netlify/functionsのインストール
Functionsを扱うための@netlify/functions
モジュールを、「netlify」ディレクトリ以下にインストールします。
% cd netlify
netlify % yarn add @netlify/functions
netlify.tomlのセットアップ
デフォルトの参照パスは「netlify/functions」なので、今回の設計では指定しなくても良いですが、明示的に指定しています。
The default location is
YOUR_BASE_DIRECTORY/netlify/functions
.
netlify.toml
# Doc: https://docs.netlify.com/configure-builds/file-based-configuration/
# ビルド設定
[build]
# 公開ディレクトリ
publish = "dist"
# 実行コマンド(target: 'static')
command = "yarn generate"
[functions]
# netlify functionsコマンドが参照するディレクトリパスを指定(default: YOUR_BASE_DIRECTORY/netlify/functions)
# [build]のbaseディレクトリが指定されている場合はそこからの相対パスとなる(default: base = "/")
directory = "netlify/functions"
"netlify/functions"
... 「functions」ディレクトリはfunctions:create
コマンドが自動生成してくれるので作成しなくて良い。
注意)functionsディレクトリをルート直下に置く場合
Functionsプロジェクトをルート直下の「functions」ディレクトリに作成する場合、functions:create
コマンドはルート直下の
この時、typescript
が自動でインストールされます。
この場合、Nuxtがインストールしたtypescript
と競合になるため、yarn dev
コマンドが正常に動きません。
- 必ず、別の
package.json に@netlify/functions
をインストールし、 netlify functions
コマンドは、- その
package.json が置かれたディレクトリ内の - 「functions」ディレクトリを参照するように設定してください。
- その
今回のFunctionsプロジェクトの設計
@netlify/functions
のインストール先 =>netlify/package.json netlify functions
コマンドが参照するディレクトリ => 「netlify/functions」
これにより、functions:create
コマンドを実行したときに、typescript
がインストールされます。
Functionsプロジェクトを作成する
ルートディレクトリからfunctions:create
コマンドを実行します。
% yarn netlify functions:create
# 使用言語はTypeScriptを選択 Enter
? Select the language of your function
JavaScript
❯ TypeScript
Go
# 作成するテンプレートは「hello-world」を選択 Enter
? Pick a template
❯ [hello-world] Basic function that shows async/await usage, and response formatting
──────────────
Clone template from GitHub URL
Report issue with, or suggest a new template
──────────────
# プロジェクト名はhello-world そのままEnter
? Name your function: (hello-world)
# プロジェクト作成完了
Installed dependencies for hello-world
✨ Done in 191.18s.
これでFucntionsのhello-world
プロジェクトが作成できました。
現在の「netlify」ディレクトリは以下の構造になっています。
netlify
├── functions
│ └── hello-world
│ └── hello-world.ts
├── node_modules
├── package-lock.json
├── package.json
└── yarn.lock
netlify/package.json
{
"name": "demo_blog_v2_functions",
"version": "1.0.0",
"private": true,
"scripts": {},
"dependencies": {
"@netlify/functions": "^0.11.0",
"@types/node": "^14.18.11",
"typescript": "^4.5.5"
}
}
Functionsのプロジェクト名はURLになる
Functionsのプロジェクト名というのは「functions」直下のディレクトリ名です。
プロジェクト名は、関数にアクセスするためのURLとなるので、-
で繋ぐケバブケースで作成することを推奨します。
hello-world.tsを改修する
自動で作成された
そこでコードを改修し、クエリを取得する関数に書き換えます。
netlify/functions/hello-world/hello-world.ts
import { Handler } from '@netlify/functions'
// any型の追加, _contextへの書き換え
export const handler: Handler = async (event: any, _context: any) => {
// 追加
const query: string = await event.queryStringParameters.q || 'No query'
return {
statusCode: 200,
body: JSON.stringify({
// queryに書き換え
message: `Hello, ${query}!`
})
}
}
event.queryStringParameters
... 関数にアクセスするURLのクエリを取得するプロパティ。URLクエリが?q=aaa
の場合は、{ q: 'aaa' }
のオブジェクトを返す。
Functionsを動かそう
ローカル環境でFunctionsプロジェクトを動かすには、Functionsのサーバーを起動する必要があります。
Functionsサーバーを起動するには、functions:serve
コマンドを実行します。
% yarn netlify functions:serve
◈ Injected .env file env var: CTF_SPACE_ID
◈ Injected .env file env var: CTF_DELIVERY_API_KEY
◈ Injected .env file env var: CTF_PREVIEW_API_KEY
◈ Injected .env file env var: APP_NAME
◈ Injected .env file env var: APP_EMAIL
◈ Loaded function hello-world (http://localhost:undefined/.netlify/functions/hello-world).
◈ Functions server is listening on 9999
ローカルFunctionsサーバーにアクセスするURLは、http://localhost:9999
となります。
Functions関数を実行する
関数を実行するには、プロジェクト毎に生成されたルートへアクセスします。
http://localhost:9999/.netlify/functions/hello-world
クエリを取得できているか確認してみましょう。
http://localhost:9999/.netlify/functions/hello-world?q=test
関数が正しく実行され、クエリを表示することができました。
コマンドでFunctions関数を確認する
コマンドでも関数の実行を確認することができます。
サーバーを起動した状態で、functions:invoke <プロジェクト名>
を実行してください。
% yarn netlify functions:invoke hello-world --port 9999
# NetlifyのID認証ヘッダをエミュレートして呼び出すか? => Yを入力
? Invoke with emulated Netlify Identity authentication headers? (pass --identity/--no-identity to override) (Y/n) Y
{"message":"Hello, No query!"}
--port 9999
...invoke
コマンドはデフォルトでポート8888
を参照する。Functionsサーバーは9999
で起動しているので、サーバーのポート番号を指定する。
Functionsサーバーのポートを変更する
functions:invoke
コマンドは、デフォルトで8888
のポート番号を参照します。
そこで、Functionsサーバーのデフォルトポート番号を8888
に変更します。
[dev]
を追加しましょう。
netlify.toml
# Doc: https://docs.netlify.com/configure-builds/file-based-configuration/
# ビルド設定
[build]
# 公開ディレクトリ
publish = "dist"
# 実行コマンド(target: 'static')
command = "yarn generate"
[functions]
# netlify functionsコマンドが参照するディレクトリパスを指定(default: YOUR_BASE_DIRECTORY/netlify/functions)
# [build]のbaseディレクトリが指定されている場合はそこからの相対パスとなる(default: base = "/")
directory = "netlify/functions"
[dev]
# functions:serveで起動するポート番号の指定(default: 9999)
functionsPort = 8888
もう一度Functionsサーバーを起動します。
% yarn netlify functions:serve
Functions server is listening on 8888
これで、functions:invoke
コマンドに--port
オプションを付与しなくて良くなります。
% yarn netlify functions:invoke hello-world
{"message":"Hello, No query!"}
今回の作業は以上です。
% git add -A
% git commit -m "Setup Netlify Functions" -m "Add Functins project for hello-world"
まとめと次回
今回は、「netlify」ディレクトリ以下にNetlify Functionsのセットアップを行いました。
そしてクエリを返すhello-world
プロジェクトを作成しました。
次回は、このプロジェクトを本番環境のNetlify Functionsにデプロイします。