imgix の無料プランでブログの記事タイトル入りOGP画像を生成してみた

# imgix とは？

https://imgix.com/

imgix は画像の配信に特化した CDN です。
URLパラメータによる画像処理機能も備わっています。

imgix の代表的な使用例といえば、やっぱり Qiita ですよね！

https://qiita.com/hareku/items/cfa2ccef7ff9a8b9c5d2

https://qiita.com/hareku/items/87a8308debe4eddb2940

imgix の公式サイトにケーススタディとしても紹介されています！

https://imgix.com/customers/qiita

特に、Qiita の記事の OGP 画像（SNS等で共有した際に表示される画像）は記事ごとにタイトルやユーザー名が表示されるようになっていますが、これは imgix によって元の画像に文字を入れることで実現しています。

# 無料プラン

このようにとても便利な機能を備えた imgix ですが、実は無料のプランが存在します。
このプランは 2021年7月に追加されました。

https://blog.imgix.com/2021/07/13/new-pricing-image-manager

以下のリソースを無料で使うことができます。

- 1,000 Origin Images
- Infinite Transformations
- Bandwidth Included
- 2 Unique Sources
- 2 Unique Users

それぞれ何がどれだけできるのかわかりにくいため、会員登録からブログの記事タイトル入りOGP画像を生成できるようになるまでの流れをこれから説明していきます。

# 会員登録からソースの作成まで

以下URLから会員登録を行います。

https://dashboard.imgix.com/sign-up

メールアドレスと名前、組織名(Organization)を入力し、登録しましょう。
無料プランの `2 Unique Users` というのは、ここで作成する Organization に2人まで追加できるということだと思います。

| メールアドレスと名前 | 組織 |
| :---: | :---: |
| ![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/69df072c-a62f-739e-0467-5aec01243e51.png) | ![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/a6927ada-b8c6-8a68-f9f8-3ff29beb522c.png) |

登録が完了したら、続いて Source を作成します。
Source はサブドメインと配信したい画像が保存されている場所を指定します。

| サブドメイン | 画像の保存されている場所 |
| :---: | :---: |
| ![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/769ee6bb-507f-79fe-e6c2-672cc5608601.png) | ![3.5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/157b7d99-ba02-4320-d67e-23f6d6cdf744.png)

配信したい画像 (Origin Image) が保存されている場所として、以下の 5種類から選択できます。

- Amazon S3
- Google Cloud Strage
- Microsoft Azure Storage
- Web Folder
- Web Proxy

上３つは有名なストレージサービスなので説明不要ですね。

Web Folder は、例えば `https://example.com/img/hoge.png` や `https://example.com/img/fuga.png` に画像をアップロードした場合、 Web Folder に `https://example.com/img/` を設定すれば、 `https://[サブドメイン].imgix.net/hoge.png`  `https://[サブドメイン].imgix.net/fuga.png` でアクセスできるようになります。

Web Proxy は様々なドメインの画像を使いたい場合に、そのURLをURLエンコードした文字列をパスに指定することでその画像を利用できます。

| 元の画像のURL | imgix から配信する際のURL |
| :---: | :---: |
| `https://example.com/hoge.png` | `https://[サブドメイン].imgix.net/https%3A%2F%2Fexample.com%2Fhoge.png` |
| `https://example.net/hoge.com` | `https://[サブドメイン].imgix.net/https%3A%2F%2Fexample.net%2Fhoge.com` |

今回は Web Proxy を選択しました。設定完了後のページに表示される以下の `SHOW TOKEN` をクリックすることで表示されるトークンは後で使用するので覚えておきましょう。

|  |
| :---: |
| ![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/a502c8a9-f5b1-50f6-3e15-9fa7415866df.png) |

Amazon S3 や Google Cloud Strage を選択した場合はストレージの識別子やアクセスキー等を設定する必要がありますが、Web Proxy は特に何も設定せずに、Sourceが作成できます。

無料プランの `2 Unique Sources` というのはここで作成できる Source が 2つということですね。

# ブログの記事タイトル入りOGP画像を生成する

以下の画像を Origin Image として、imgix でタイトルを入れた画像を生成してみます。

| 以下の画像に文字を入れます |
| :---: |
| ![](https://user-images.githubusercontent.com/34445284/170053649-3882bfb2-a8dc-49e5-80f4-c633186c7784.png) |

対象のブログは僕が以前チュートリアル通りに作った Next.js のブログです。

https://www.wataru86.ml/

imgix 公式から、様々なプログラミング言語で記述できるように各言語用のライブラリが公開されています。
今回は TypeScript で処理を書くため、以下のライブラリを用いてでタイトルから画像を作成する関数を実装します。

https://github.com/imgix/js-core

`yarn add @imgix/js-core` 等でパッケージを追加したら、早速実装してみましょう！
`new ImgixClient` で サブドメインとURLトークンを指定し、クライアントを作成します。

```TypeScript:lib/imgix.ts
import ImgixClient from '@imgix/js-core'

const client = new ImgixClient({
  domain: 'wataru86.imgix.net',
  secureURLToken: process.env.IMGIX_TOKEN,
})
```

URLトークンは先ほどの Source 作成後のページに表示されるトークンを設定すればOKです。
上記の例では `.env` ファイルに `IMGIX_TOKEN=XXXXXXXXX` のようにトークンを設定して、`process.env` から参照できるようにしています。

`client.buildURL` で土台となる画像のURLと、どのように画像を処理するか指定したパラメータを渡すことで、URLが作成されます。今回はタイトルを引数に取り、画像上に文字を設定する `buildOgImageUrl` を作りました。

```TypeScript:lib/imgix.ts
export const buildOgImageUrl = (title: string) => {
  return client.buildURL(baseImageUrl, {
    mark64: client.buildURL('~text', {
      w: 1000,
      txt: title,
      'txt-size': 75,
      'txt-align': 'middle,center',
    }),
    'mark-x': 90,
    'mark-y': 180,
  })
}
```

ここで `buildURL` の第一引数に指定する画像の数が、Origin Image の数となります。
無料プランは `1,000 Origin Images` なので、1,000 種類の画像まで使用できます。

また、プランに `Infinite Transformations` と書いてあるとおり、一つの画像に対してどれだけ変換しても無料です。


作成した関数を記事ページの `getStaticProps` 内で呼び出し、imgix で作成した OGP の画像の URL を `props` として渡すようにしてあげます。

```diff_typescript:pages/posts/[id].tsx
+import { buildOgImageUrl } from '../../lib/imgix'

export default function Post({
  postData,
+ ogImageUrl
}: {
  postData: {
    title: string
    date: string
    contentHtml: string
  },
+ ogImageUrl: string,
}) {
  return (
+   <Layout ogImageUrl={ogImageUrl}>
      <Head>
        <title>{postData.title}</title>
      </Head>
=============(中略)==================

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const postData = await getPostData(params.id as string)
+ const ogImageUrl = buildOgImageUrl(postData.title)
  return {
    props: {
      postData,
+     ogImageUrl,
    }
  }
}
```

最後に、渡した `ogImageUrl` を `og:image` に指定したら完成です！

```diff_typescript:components/layout.tsx
export default function Layout({
  children,
  home,
+ ogImageUrl,
}: {
  children: React.ReactNode
  home?: boolean
+ ogImageUrl?: string
}) {
  return (
    <div className={styles.container}>
      <Head>
        <link rel="icon" href="/favicon.ico" />
        <meta
          name="description"
          content="Learn how to build a personal website using Next.js"
        />
+       {ogImageUrl && (
+        <meta
+           property="og:image"
+           content={ogImageUrl}
+        />
+       )}
```

これで以下のように各記事のタイトルが入ったOGP画像が表示できるようになりました。

https://www.wataru86.ml/posts/ssg-ssr

https://www.wataru86.ml/posts/pre-rendering

↑ 見えていますか？ドメイン更新忘れ等、何かやらかした場合画像が見えなくなってしまうので、念のためスクショも載せておきます。

|  |
| :---: |
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325392/fe78bda8-3eb3-51ba-a8dc-6012c41d6f2a.png) |

URLを見てみると、末尾に `s=775ebf5f34581940348eba8cdcb64a2b` というパラメータがありますね。
これはパス・パラメータ・トークンを元にMD5で生成したハッシュであり、これにより第三者により変換方法等を変更したURLが作成されてしまうことを防ぎます。

```
https://wataru86.imgix.net/https%3A%2F%2Fuser-images.githubusercontent.com%2F34445284%2F170053649-3882bfb2-a8dc-49e5-80f4-c633186c7784.png?ixlib=js-3.6.0&mark64=aHR0cHM6Ly93YXRhcnU4Ni5pbWdpeC5uZXQvfnRleHQ_aXhsaWI9anMtMy42LjAmdz0xMDAwJnR4dD1XaGVuJTIwdG8lMjBVc2UlMjBTdGF0aWMlMjBHZW5lcmF0aW9uJTIwdi5zLiUyMFNlcnZlci1zaWRlJTIwUmVuZGVyaW5nJnR4dC1zaXplPTc1JnR4dC1hbGlnbj1taWRkbGUlMkNjZW50ZXImcz1iNzBiYTk3OTgxMzQ2M2RiYzZmNjg1ODI0NjgzYTcyZA&mark-x=90&mark-y=180&s=775ebf5f34581940348eba8cdcb64a2b
```

# まとめ

imgix 無料プランで個人ブログの記事タイトル入りOGPの作成ができました。
以下のリソースを無料で使うことができます。

- 1,000 Origin Images
    - 最大1,000種類の画像を元に、変換を行うことができます。
- Infinite Transformations
    - Origin Imagesの上限を超えない限り、どのように変換しても無料です。
- Bandwidth Included
    - これはちょっとよくわからなかったのですが、以下のような記述があったので、転送量がOrigin Imageごとに月100MBを置けなければ問題ないということだと思います。
        - `Excessive bandwidth usage above 100 MB per month per Origin Image included in each plan will be monitored by our team. `
- 2 Unique Sources
    - Source (サブドメイン + 保存場所) を2個まで設定できます。
- 2 Unique Users
    - Organization に2人まで追加できます。