Komesan: 指定したURLに関連するはてなブックマーク、Twitter、HackerNewsのコメントを表示する
Komesanというはてなブックマーク、Twitter、HackerNewsをまとめて表示するサイトを作りました。
- https://komesan.pages.dev/?url=https://pages.cloudflare.com
- HackerNewsはオプショナル: https://komesan.pages.dev/?url=https://pages.cloudflare.com&service=hackerNews
ブックマークレットで実行する場合は、次のようなURLのブックマークを利用します。サイトの下部に同じものがおいてあります。
javascript:void(window.open("https://komesan.pages.dev/?url="+encodeURIComponent(location.href)))
自分用のツールでなので、iframe表示用の変な機能もありますが、READMEとか読んでください。
- はてなブックマークは、はてなブックマークのAPIを利用しています
- Twitterは、Twitter v2 APIの検索APIを利用しています
- HackerNewsは、AlgoliaのHackerNews APIを利用しています
元のデータは、元サイトのAPIを使って取得しているだけです。
作った理由
同様の機能を持つサイトとして http://komepon.net がありますが、HTTPSに対応してなかったのが気になりました。 あと、Remixを使って何か作ってみたくて、検索結果を表示するのは題材としてちょうど良さそうでした。
Remix
Komesanは、Cloudflare PagesとRemixを使って動いています。
KomesanのやっていることはAPIの結果を加工して表示するという感じです。 Remixの題材としてちょうど良さそうなので、Remixを使ってみました。 Remixについては作者による記事を見るのがよいと思います。
Remixのphilosophyにあるように、Komesanも特に意識せずに基本的な機能はJavaScriptが無効でも動いているようでした。
RemixはCloudflare Workers/Cloudflare Pagesにデプロイできるので、Cloudflare Pagesでサーバを動かすフレームワークとして便利だと思います。(Next.jsだと結構面倒です。)
Web Standards, HTTP, and HTMLを基本としてるのもあって、Cloudflare WorkersのようなService WorkerライクなAPIのみがある場所で使うのに適したデザインだと思います。
ルーティングは、Next.jsなどのフレームワークとあまり変わりません。
データの読み込みは、loader
という関数を定義するとサーバサイドでデータを取得してReactに渡すPropsのデータを作って渡します。
初回のレンダリングはサーバサイドレンダリングで、Form
でのデータ送信、Link
でのページ移動時は、PropsのデータだけをFetchしてPA的な遷移ができます。
データの書き込みは少し変わっていて、Formを使ったPOSTが基本となっています。
<Form>
コンポーネントというform要素のラッパーが用意されているので、これを使ってサーバにデータを送信します。
サーバではaction
という関数を定義すると、Formのから送信されたデータが受け取れます。
受け取るデータもウェブ標準のFormDataとなっています(これによってJSが無効でも動く)。
全体的に特定の名前でexportしたら、その機能となるようなデザインです。
export const loader: LoaderFunction = () => {
return [{ name: "Pants" }, { name: "Jacket" }];
};
export const action: ActionFunction = ({ request }) => {
const body = await request.formData();
const project = await createProject(body);
redirect(`/projects/${project.id}`);
}
export default function Products() {
return <div>App</div>
}
全体的に明示的に型をつけないと型がつかない感じな気はしました(この辺はNext.jsもあんまり変わらない印象)。 バリデーションは、サンプルコードでtiny-invariantが使われてるぐらいで、ユーザー側でやる感じです。
基本的には覚えることが少ないようなデザインになっていそうでした。 今回のKomesanは一種の検索ページというRemixのユースケースとしてぴったりな感じだったからかもしれません。
JavaScriptとFetchを使った通信が色々発生するアプリケーションの場合は、usefetcher
やuseTransition
を使う必要があったりして、Remix特有の事柄が増えそうな感じはしました。
Cloudflare Pages
RemixはCloudflare Pagesに対応しています。 最初のテンプレート選択でCloudflare Pagesを選べるので、それを選んでCloudflare Pagesにデプロイします。
npx create-remix@latest
Cloudflare Pages側のドキュメントに従って、生成されたコードをもつGitHubリポジトリと接続するだけでOKです。
ローカル開発の場合は、絶賛開発中のwrangler2のalphaが使われているので、ちょっとはまりどころがありました。
wrangler2はMiniflareが元となった、ローカルでのエミュレート機能が入っています。
ローカルでCloudflare Workers KVをエミュレートするには--kv
という引数を使います。
"dev:wrangler": "wrangler pages dev ./public --watch ./build --kv NAMESPACE --binding $(cat .env)",
また、.env
ファイルが読み込める風のドキュメントになっていますが、Cloudflare Pagesの場合は.env
は読み込まれないので--binding
という引数で環境変数を渡してあげる必要があります。
この辺は、成熟したら解決してくるかなという感じはします。
パフォーマンス
単純なページなので、特別なことはありませんでした。
サーバサイドレンダリング時に、はてなブックマークとTwitterのAPIを叩いているので、その待ち時間がそのままTTFBに反映されます。 Hacker NewsのAPIは、あんまり速くないのでオプトインにしました。 はてなブックマークは、ブックマーク数に応じて重くなるので、ブックマーク数が多いページは表示が遅いです。
HatenaBookMark: 81ms
Twitter: 276ms
HackerNews: 998ms
リアルタイム性は必要ない(元ページを見ればいいだけなので)と思ったので、60秒ぐらいのキャッシュをしています。
まとめ
PCとかモバイルとかどこでも使えるコメント表示するやつが欲しくなったので、Komesanを作りました。
KomesanはCloudflare PagesとRemixを使って動いています。
ソースコードも公開してるので、Forkして、Twitter v2のAppを作ってTWITTER_TOKEN
という環境変数にBearer Tokenを設定すれば、自分用のkomesanが動かせます。
- azu/komesan: View comments about the site
- デプロイ方法あんまり細かく書いてないので、興味ある人はPRで足してください
- https://github.com/azu/komesan#deployment
RemixはCloudflare Pages/Workers向けのフレームワークという視点でみると便利だなーと思いました。 Nuxt 3もCloudflare Workersとしてデプロイできたり、その方向が強くなっていきそうな気がしました。
- Nuxt - Introducing Nuxt 3 Beta
- Moving Nitro to standalone bundler · Discussion #1690 · nuxt/framework
あと、Cloudflare Workers向けのフレームワークであるworktopを作ってたLuke EdwardsがCloudflareの人になってたりしていました。 (polkaとかklonaとかファイルサイズが小さいモジュールをよく作っている人)
CloudflareがLincを買収してたので、Cloudflare側が何かアプリケーションフレームワークを提供するのかなーと考えていました。
Remixなどを見てると、思っていたより速く、別のものがCloudflare Workersのフレームワークとして使えるようになっていきそうでした。
同じくService Workers的なAPIを持つDeno Deployとかでも動くようになっていくので、やっとアプリケーションを普通に書いてEdgeにデプロイできるようになっていきそうです。
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。