Netlify Edge FunctionsでWebページのOGPデータを取得する関数を作る
このブログでは、外部のWebサイトの埋め込みパーツをiFramelyを使って実装していた。
ただ表示されるまでに少し遅延があったり、気軽にスタイルを変更したりしたいので、自分で実装することにする。
Webページから直接HTMLを取得するとCORS制約にかかってしまう。
そのためHTMLをパーズしてOGPのメタ情報を返すAPIを、Netlify Edge Functionで実装する。
このページでは、次のEdge Functionを作る。 クエリ文字列にOGPを取得したいWebページのURLを指定してGETリクエストを送信すると、WebサイトのOGPをJSON形式で取得するEdge Functionを作る。
この記事で作成するEdge Functionは、chick-p/netlify-edge-function-ogpに置いている。
Netlify Edge Functionsとは
Netlify Edge Functionsは、Netlifyが提供する、ユーザーのロケーションに近いエッジ環境でサーバーレス環境である。
ほかの同様のサービスには、AWSのCloudFront FunctionsやCloudflareのCloudflare Workersがある。
Netlify Edge Functionsの特徴は、次のとおり。
- Deno Deployを採用しているため、TypeScriptやJavaScriptで書くことができる
- メモリは512MB、CPU時間は50ミリ秒以内という制約がある
- Netlifyのフリープランの場合、3分/月まで実行できる
Edge Functionは次の3ステップで作成できる。
netlify/edge-functions
というディレクトリの中に実行するスクリプトを置くnetlify.toml
に呼び出すスクリプトとルーティングの設定を書く- Netlify CLIを使ってデプロイする
いくつかEdge Function のサンプルがGitHubに公開されているので、書き方がわからない場合にはこれらのサンプルを参考にするとよさそう。
WebページのOGPデータを取得するNetlify Edge Functionsを作る
動作を確認した環境
Netlify CLI v11.5.1
STEP0:事前準備
プロジェクトのディレクトリに、次の構成でディレクトリとファイルを作成する。
ファイルはまだ空のままで良い。
.
├── netlify
│ └── edge-functions
│ └── get-meta.ts
└─── netlify.toml
STEP1:スクリプトを作る
netlify/edge-functions/get-meta.ts
を開き、次の内容を記載する。
Netlify Edge Functionsでは、export defaultするハンドラーの第一引数でリクエストを受け取り、Response
オブジェクトを返却する。
import { Context } from "https://edge.netlify.com";
import { DOMParser } from "https://deno.land/x/deno_dom/deno-dom-wasm.ts";
type Meta = Record<string, string>;
function extractOgp(metaElements: HTMLMetaElement[]): Meta {
return metaElements
.filter((element: HTMLMetaElement) => element.hasAttribute("property"))
.reduce<Meta>((prev, element) => {
const property = element.getAttribute("property")?.trim();
if (!property) return { ...prev };
const content = element.getAttribute("content") || "";
return {
...prev,
[property]: content,
};
}, {});
}
// eslint-disable-next-line import/no-anonymous-default-export
export default async (
request: Request,
context: Context
): Promise<Response> => {
const url = new URL(request.url).searchParams.get("url"); // クエリ文字列を受け取る
if (!url) {
return context.json({ error: "The query parameter of url is required." });
}
const resp = await fetch(url);
const html = await resp.text();
const document = new DOMParser().parseFromString(html, "text/html");
const meta = document?.querySelectorAll("meta");
if (!meta) {
return context.json({ error: "Meta element are not found." });
}
const ogp = extractOgp([...meta]);
const response = await context.json(ogp);
// CORS 対策
response.headers.set("Access-Control-Allow-Origin", "*");
response.headers.set("Access-Control-Allow-Methods", "GET");
return response;
};
STEP2:呼び出すスクリプトとルーティングの設定を書く
netlify.toml
内の[[edge_function]]
というセクションで、スクリプトとルーティングの関係を定義する。
この関数では、クエリ文字列を渡せるようにしたいので末尾に*
というワイルドカードをつける。
[build]
command = "echo No build for this site, we are living on the edge"
publish = "."
[[edge_functions]]
function = "get-meta"
path = "/get-meta*"
STEP3:デプロイする
デプロイには、Netlify CLIを使う。
グローバルインストールすると、netlify
というコマンドが使えるようになる。
$ npm install netlify-cli -g
まずはローカル環境で動作を確認する。プロジェクトのディレクトリで次のコマンドを実行する。
$ netlify dev
◈ Netlify Dev ◈
◈ Ignored general context env var: LANG (defined in process)
◈ No app server detected. Using simple static server
◈ Running static server from "netlify-edge-function-ogp"
◈ Setting up local development server
────────────────────────────────────────────────────────────────
Netlify Build
────────────────────────────────────────────────────────────────
❯ Version
@netlify/build 27.16.1
❯ Flags
{}
❯ Current directory
/Users/chick-p/works/netlify-edge-function-ogp
❯ Config file
/Users/chick-p/works/netlify-edge-function-ogp/netlify.toml
❯ Context
dev
────────────────────────────────────────────────────────────────
1. Run command for local development
────────────────────────────────────────────────────────────────
◈ Static server listening to 3999
(dev.command completed in 8ms)
┌─────────────────────────────────────────────────┐
│ │
│ ◈ Server now ready on http://localhost:8888 │
│ │
└─────────────────────────────────────────────────┘
◈ Loaded edge function get-metas
http://localhost:8888/get-meta?url=https://blog.chick-p.work
にアクセスして、OGP情報に関するJSONが返ってくれば成功となる。
Netlifyにデプロイするには、プロジェクトのディレクトリで次のコマンドを実行する。
# プレビュー環境の場合
$ netlify deploy --build
# プロダクション環境の場合
$ netlify deploy --build --prod
コマンドを実行するとNetlifyにログインすることを求められ、アプリを新しく作るかどうかを尋ねられる。 新しくアプリを作ることを選択すると、デプロイが始まる。
$ netlify deploy --build --prod
Packaging Edge Functions from netlify/edge-functions directory:
- get-meta
(Edge Functions bundling completed in 2.4s)
────────────────────────────────────────────────────────────────
Netlify Build Complete
────────────────────────────────────────────────────────────────
(Netlify Build completed in 2.5s)
Deploy path: /Users/chick-p/works/netlify-edge-function-ogp
Configuration path: /Users/chick-p/works/netlify-edge-function-ogp/netlify.toml
Deploying to main site URL...
✔ Finished hashing 5 files and edge functions
✔ CDN requesting 0 files
✔ Finished uploading 0 assets
✔ Deploy is live!
Logs: https://app.netlify.com/sites/foo/deploys/63145a19063a093f65a88c86
Unique Deploy URL: https://63145a19063a093f65a88c86--foo.netlify.app
Website URL: https://foo.netlify.app
実行結果の最後の「Website URL」がEdge FunctionをデプロイしたアプリのURLになる。
URLの末尾に/get-meta?url=OGP情報を取得したいURL
を実行して、ローカル環境で確認結果と同様に、OPG情報のJSONが返ってくれば成功である。