Skip to content

Commit

Permalink
feat: cloudflareのプラグインで実装してみる
Browse files Browse the repository at this point in the history
  • Loading branch information
吉野敬太郎 authored and 吉野敬太郎 committed Sep 16, 2024
1 parent 98a6eef commit 1e30a08
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 69 deletions.
2 changes: 1 addition & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default defineConfig({
site: "https://yukky-sandbox.dev/",
vite: {
optimizeDeps: {
exclude: ["fsevents"],
exclude: ["fsevents", "@cloudflare/pages-plugin-vercel-og"],
},
},
output: "hybrid",
Expand Down
Binary file modified bun.lockb
Binary file not shown.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,21 @@
"@astrojs/react": "^3.6.2",
"@astrojs/rss": "^4.0.7",
"@astrojs/tailwind": "^5.1.0",
"@cloudflare/pages-plugin-vercel-og": "^0.1.2",
"@formkit/tempo": "^0.1.2",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"astro": "4.15.6",
"microcms-js-sdk": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"satori": "^0.11.0",
"sharp": "^0.33.5",
"tailwindcss": "^3.3.3",
"typescript-eslint": "^7.2.0"
},
"devDependencies": {
"@playwright/test": "^1.36.2",
"@tailwindcss/typography": "^0.5.9",
"@types/bun": "^1.0.8",
"@types/sharp": "^0.32.0",
"eslint": "^8.46.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard-with-typescript": "^43.0.1",
Expand Down
77 changes: 47 additions & 30 deletions src/pages/og/_OgImage.tsx → src/functions/post/_middleware.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import satori from "satori";
import sharp from "sharp";
import React from "react";
import vercelOGPagesPlugin from "@cloudflare/pages-plugin-vercel-og";

interface OgImageProps {
text: string;
ogTitle: string;
}

const OgImage = ({ text }: OgImageProps): JSX.Element => {
const OgImage = ({ ogTitle }: OgImageProps): JSX.Element => {
return (
<div
style={{
Expand Down Expand Up @@ -36,7 +36,7 @@ const OgImage = ({ text }: OgImageProps): JSX.Element => {
paddingLeft: "48px",
}}
>
<h1>{text}</h1>
<h1>{ogTitle}</h1>
<div
style={{
display: "flex",
Expand Down Expand Up @@ -82,31 +82,6 @@ const OgImage = ({ text }: OgImageProps): JSX.Element => {
</div>
);
};
export async function getOgImage(text: string): Promise<Buffer> {
const notoSansJpUrl = `https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@600`;
const reggeaeOneUlr =
"https://fonts.googleapis.com/css2?family=Reggae+One&display=swap&text=ゆっきーの砂場";
const notoSansJpFontData = await getFontData(notoSansJpUrl);
const reggeaeOneFontData = await getFontData(reggeaeOneUlr);
const svg = await satori(<OgImage text={text} />, {
width: 800,
height: 400,
fonts: [
{
name: "Noto Sans JP",
data: notoSansJpFontData,
style: "normal",
},
{
name: "Reggae One",
data: reggeaeOneFontData,
style: "normal",
},
],
});

return await sharp(Buffer.from(svg)).png().toBuffer();
}

const getFontData = async (url: string): Promise<ArrayBuffer> => {
const css = await (
Expand All @@ -128,3 +103,45 @@ const getFontData = async (url: string): Promise<ArrayBuffer> => {

return await fetch(resource[1]).then(async (res) => await res.arrayBuffer());
};

export const onRequest = async () => {
const notoSansJpUrl = `https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@600`;
const reggeaeOneUlr =
"https://fonts.googleapis.com/css2?family=Reggae+One&display=swap&text=ゆっきーの砂場";
const notoSansJpFontData = await getFontData(notoSansJpUrl);
const reggeaeOneFontData = await getFontData(reggeaeOneUlr);
return vercelOGPagesPlugin<OgImageProps>({
imagePathSuffix: "/og-image.png",
component: ({ ogTitle }) => {
return <OgImage ogTitle={ogTitle} />;
},
extractors: {
on: {
'meta[property="og:title"]': (props) => ({
element(element) {
props.ogTitle = element.getAttribute("content");
},
}),
},
},
options: {
width: 800,
height: 400,
fonts: [
{
name: "Noto Sans JP",
data: notoSansJpFontData,
style: "normal",
},
{
name: "Reggae One",
data: reggeaeOneFontData,
style: "normal",
},
],
},
autoInject: {
openGraph: true,
},
});
};
9 changes: 2 additions & 7 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ export interface Props {
title: string;
description: string;
ogType?: string;
ogImageUrl?: string;
}
const { title, description, ogType, ogImageUrl } = Astro.props;
const { title, description, ogType } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---

Expand All @@ -26,17 +25,13 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
<meta property="og:description" content={description} />
<meta property="og:type" content={ogType ?? "website"} />
<meta property="og:url" content={Astro.url} />
{ ogImageUrl !== undefined ? <meta property="og:image" content={ogImageUrl} /> : '' }
{ ogImageUrl !== undefined ? <meta property="og:image:width" content="800" /> : '' }
{ ogImageUrl !== undefined ? <meta property="og:image:height" content="400" /> : '' }
<meta property="og:site_name" content="ゆっきーの砂場" />
<meta property="og:locale" content="ja_JP" />
<meta property="twitter:site" content="@Yu_yukk_Y" />
<meta property="twitter:creator" content="@Yu_yukk_Y" />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
{ ogImageUrl !== undefined ? <meta property="twitter:card" content="summary_large_image" /> : <meta property="twitter:card" content="summary" /> }
{ ogImageUrl !== undefined ? <meta property="twitter:image" content={ogImageUrl} /> : '' }
<meta property="twitter:card" content="summary_large_image" />
<meta name="msapplication-config" content="/browserconfig.xml">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
Expand Down
5 changes: 2 additions & 3 deletions src/layouts/PostLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ export interface Props {
title: string;
description: string;
createdAt: string;
slug: string;
}
const { title, description, createdAt, slug } = Astro.props;
const { title, description, createdAt } = Astro.props;
const OG_TYPE = "article";
const dateTypeCreatedAt = new Date(createdAt);
---

<Layout title={title} description={description} ogType={OG_TYPE} ogImageUrl={`https://yukky-sandbox.dev/og/${slug}.png`}>
<Layout title={title} description={description} ogType={OG_TYPE}>
<article
class="mt-5 pt-5 lg:w-1/2 bg-amber-50 dark:bg-gray-500 w-full"
>
Expand Down
24 changes: 0 additions & 24 deletions src/pages/og/[...slug].png.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/pages/post/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export async function getStaticPaths() {
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<PostLayout title={entry.data.title} description={entry.data.description} createdAt={entry.data.createdAt} slug={entry.slug}>
<PostLayout title={entry.data.title} description={entry.data.description} createdAt={entry.data.createdAt}>
<Content />
</PostLayout>

0 comments on commit 1e30a08

Please sign in to comment.