辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

使用 Nitro + Serverless 関数で動的なヘッダーバナーを実現する

image.png

関連する内部リンク:

  • [[速通 - unjs 家族の Web フレームワーク Nitro]]
  • [[速通 - 腾讯云云函数 scf]]
  • [[記事にバナーを追加するためのツールの作成]]
  • [[速通 - 動的 SVG 画像生成のソリューション Satori]]

背景#

現在、記事のトップにはタイトルを含む画像を追加することが一般的です。異なるプラットフォームでは、最初の画像がデフォルトで使用される場合があります。これは、記事のバナー、カバー、ヒーローイメージなどと見なされることがあります。

以前の [[記事にバナーを追加するためのツールの作成]] の記事では、ページ上でバナーを操作して生成するウェブサイトを作成したことを紹介しました。

しかし、xx.com/cover?title=xxxにアクセスすると、自動的に画像が返されるサービスを直接作成する方法はありますか?その場合、ページを開いて作成する必要はありません。後でログを確認するだけで、アクセスした人数がわかります!

また、ブラウザとは異なり、node.js では画像のレンダリングが少し複雑になります。計算やレンダリングの能力をブラウザに任せることはできません。最も直接的な方法は、html+css でスクリーンショットを生成することはできません。なぜなら、node.js 環境では css のレンダリング能力がないため、canvas/svg などの方法を使用して描画する必要があるからです。

Canvas のクロスプラットフォーム互換性が発揮されます。しかし、Canvas にはあまり触れたことがなく、あまりわかりませんでした。後で svg も非常に簡単で、文字列が返されるため、サイズも小さくなります。

一つのことを選ぶことはできません。

要件設計#

まず、これは node のサービスです。パラメータを持ってインターフェースを要求し、返されるのは画像です。したがって、バックエンドをデプロイする必要があります。

同じ要求パラメータには同じ結果が表示されるべきです。主に背景画像ですが、ページをリロードすると画像が変わることは避けたいです。

将来的には異なるテンプレートを追加することができ、サービスを外部に提供することもできるようにしたいです。

望ましいパラメータ:

  • 高さ(オプション、自動的に設定されます)
  • 比率 4:3 16:9 21:9 2:1 1:1 など
  • タイトル テキストの内容
  • ソース マーク、例:@ijust.cc
  • 指定した色相 0-360
  • デフォルトでグラデーションの linear-gradient を有効にする

これで、基本的には https://ijust.cc/tools/canvas のウェブバージョンと同じになります。

技術設計#

ホスティング#

node サービスのホスティングは、明らかに serverless を使用することができます。国内のクラウドプロバイダーサービスを選択することもできますし、cloudflare/vercel が提供するサービスを使用することもできます。サービスの正常な運用のためには移行が必要な場合もあるため、serverless フレームワークを選択することができます。以前に言及した [[速通 - unjs 家族の Web フレームワーク Nitro]] は非常に役立ちます。Nitro を使用すると、さまざまな成果物を簡単に構築できます。

ここでは、腾讯云の Serverless 関数を使用します。後で Cloudflare Workers を補完します。

テーマカラーの永続化#

同じ内容から同じ結果が生まれるようにするために、タイトルの内容に基づいて主要な色を計算する方法を設計します。GPT にいくつかの方法を尋ねましたが、各文字列に対して charCodeAt を計算し、得られた数字を処理する方法などがあります。

function stringToDegrees(inputString) {
    let hash = 0;
    for (let i = 0; i < inputString.length; i++) {
        let char = inputString.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash |= 0; // ハッシュ値を32ビット整数に変換する
    }
    return Math.abs(hash % 360);
}
stringToDegrees('中文') // 194

Satori を使用した動的な SVG の作成#

キャンバスは SVG 技術の制約のため、z-index をサポートしていません。transform もサポートしていません。フレックスレイアウトを使用する必要があります。フォントを指定する必要があります。webp/avif などの画像形式はサポートされていません。hsl カラーフォーマットもサポートされていません。

しかし、幸いなことに、それほど複雑なものではなく、スタイルを微調整すれば使用できます。

私のバナーにはアバターがありますが、svg は base64 で埋め込む必要があります。サイズが大きくなる可能性があります。画像サイズを減らすために、svg に変換し、avif/webp などの形式に変換しましたが、あまり満足していませんでした。

最終的には、色を減らした png を使用しました。24 色で十分だと感じました。png のサイズを 5〜6 倍縮小することができ、肉眼では差異がわかりません。非常に良いです。

技術実装#

ここでは、すべてを説明するために新しいリポジトリを準備し、将来的には共有コンテンツとして使用することもできます。

コードはこちらにあります:https://github.com/Otto-J/serverless-dynamic-banner

私はコードを書くために行ってきます。コードを書いたら戻ってきて補完します。

時間が経ち、やっと書き終わりました。serverless サービスもオンラインで使用できるようになりました。たくさんの愚痴が出てきました、イライラ😡。

踏み込んだ経験#

前述のように、技術選択は nitro + 腾讯云 serverless でした。目標は serverless サービスをオンラインにすることで、最終的には URL を手に入れて画像が表示されるページを開くことです。

Nitro ドキュメントの質が低い#

私が nitro を選んだ理由は 2 つあります:

  • 新しい構文を学ぶ必要がないため、例えば next.js の概念など、簡単に始めることができます。express/koa と比較してもおもちゃではなく、ts、ルーティング、ミドルウェア、一般的なメソッドが組み込まれており、実際のビジネスコードをより速く簡単に書くことができます。
  • Nitro は nuxt の一部であり、Nitro を学ぶと、バックエンドサービス、フルスタックサービスの両方に使用できます。経験を直接再利用できます。

問題は、ルート情報を取得したり、返される情報を設定したりするなど、ルーティングの詳細や技術的な詳細をどのように学ぶかです。GPT に尋ねても、このような新しいものはわかりません。ドキュメントとチュートリアルを見るしかありません。

Nitro のドキュメントは数ページしかなく、中国語ではありません。機能の紹介は PPT のようで、プレイグラウンドもなく、API の索引も見つかりませんでした。イライラして、ガイド + API の索引 + プレイグラウンド + プロジェクトの実践は標準装備ではないですか!

image.png

しかし、私はエキスパートです。幸いなことに、Nitro ([[速通 - unjs 家族の Web フレームワーク Nitro]]) は unjs/h3 ([[unjs_h3]]) のラッパーであることを知っています。h3 は低レベルの API を提供し、nitro は高レベルのラッパーであり、すぐに使用できます。したがって、h3 のドキュメントを見るべきです。私は賢いですね。

GitHub で unjs h3 を検索し、https://github.com/unjs/h3 の結果を開きます...

image.png

やめましょう、教えましょう。API の索引はここにあります、h3 の長いドキュメントの最後にあります。

image.png

返すときに content-type を svg に指定する方法は?自分で試してみてください。結論はsendメソッドを使用することです。

そうそう、もし Nuxt ユーザーなら、Nuxt ドキュメント - Nitro ドキュメント - h3 ドキュメントの順番で学ぶ必要があります。

腾讯云 Serverless 関数の体験が非常に悪い#

前述のように、腾讯云は大手企業であり、信頼できると考えられています。また、1 年以上の実績があります。

しかし、実際の体験は非常に悪いです。私が想像していたクラウド関数のオンラインプロセス:

  • GitHub 情報を承認し、プロジェクトを読み取る
  • プロジェクトのソースコードを選択し、基本情報を自動的または手動で選択し、ビルドを行う
  • 提供された成果物をクラウドにアップロードする
  • アドレスを教えてくれるので、クリックするとアクセスできる
  • カスタム URL を設定できるようになりました。セキュリティと他のサービスのプロモーションのために、ゲートウェイの認証、モニタリング、ログなどを有効にすることをお勧めします
  • 使用してください。クォータが足りない場合は、プランを購入できます

合理的ですね、ユーザーサービスが良く、他のビジネスサービスも提供できます。

実際はそうではありません。各ステップには多くのエラー、多くの関連技術概念、多くの質問マークのヘルプドキュメントがあります。フロントエンドでサービスをオンラインにするのは簡単で、技術的な難しさがないと思われることを心配しているようです。

愚痴を言う力がありません、書かないでください、幸いなことに、終わりました。

image.png

image.png

image.png

後で別の文書で説明します。

DNSPOD が腾讯云に統合されない#

DNSPOD は腾讯云に買収され、現在は腾讯云の一部です。ドメイン、レコード、解析など、私のドメインはすべて腾讯云と DNSPOD にありますが、DNS 解析を開始すると、ページを開いてログインし、QR コードをスキャンし、書き込む必要があります。

非常に面倒です。

自分が愚かなファイルを間違った場所に置いてしまった#

私のソースコードを見ればわかりますが、ディレクトリをきれいにするためにラップしましたが、うっかり忘れて、一部のファイルを外側に置いてしまいました。どうしても取得できない、ふふ、後で別のプロジェクトを開くと、乱れると困ります。

satori は css や画像の機能をサポートしていない#

svg の制約により、satori は z-index をサポートしていません。transform もサポートしていません。flex レイアウトを使用する必要があります。フォントを指定する必要があります。webp/avif などの画像形式はサポートされていません。hsl カラーフォーマットもサポートされていません。

しかし、幸いなことに、それほど複雑なものではなく、スタイルを微調整すれば使用できます。

私のバナーにはアバターがありますが、svg は base64 で埋め込む必要があります。サイズが大きくなる可能性があります。画像サイズを減らすために、svg に変換し、avif/webp などの形式に変換しましたが、あまり満足していませんでした。

最終的には、色を減らした png を使用しました。24 色で十分だと感じました。png のサイズを 5〜6 倍縮小することができ、肉眼では差異がわかりません。非常に良いです。

結論と展望#

作業は完了しましたが、感じ方はどうですか、昨日はイライラしましたが、今日は書き終わりました。

次回も来て、もう少し早くなることを願っています。

国内のクラウドサービスは価格競争がありますが、位置があります。ビジネスに専念し、良いサービスを提供する必要があります。スムーズなサービスの使用は標準装備であるべきです。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。