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 が返ってくれば成功である。