ポートフォリオサイトを新たに制作しました。
はじめに
夏休み期間中に以前作ったポートフォリオサイトよりもモダンでおしゃれなポートフォリオサイトを作りたいと思い立って制作しました。 また制作に当たって各要件を分解してそれぞれの目標を達成できるように、技術構成や画面構成を練りました。
技術構成
web framework
- Astro
- React
- vite
Linter & Formatter
- Biome
- Prettier
Dev
- Git / GitHub
- Storybook
Deploy
- Vercel
Write Posts
backend
- hono
- @octokit/rest
- Cloudflare Workers
Analytics
- Google Analytics
技術構成に関する簡単な説明
もっと詳しく知りたい方は #より詳しいポートフォリオ作成の際の構想 を参照してください
Astro を採用した理由
今回は静的なサイトを作りたかったので Vite + React の選択肢はありませんでした。次に候補に上がったのが Next.js でしたが、SSR をしないためフレームワークとして大きすぎると思ったため不採用に。
SSG ができて css module と scss と react と storybook が使えるフレームワークで必要十分だと感じたため採用しました。
実装してみて SSG の快適さを身に沁みて感じています。これまでのポートフォリオに比べて本当に軽くなって、表示までの時間が短くなっていて嬉しいです。
Biome を採用した理由
応援しているから
hono を採用した理由
一番書きやすいと感じるバックエンドフレームワークであるため
また Cloudflare Workers でのデプロイの手間がほとんどかからないかつ、ログも確認しやすいため
esa を採用した理由
一番使いやすいオンラインの markdown 編集ツールであると感じるため
かつ webhook で markdown の変更内容をバックエンドで利用できるため
この記事もesaを使って書いています
こんな素晴らしいサービスを学生には無料で使わせてくださるesaの方には感謝しかないです
Posts と Works の内容を自動で更新するシステムの構築
一度ページを見て確認して欲しいのですが、 Posts と Works のそれぞれのページはハードコーディーングを行っているわけではありません
Release ブランチ の /posts ディレクトリにコミットされる Markdown ファイル の中身を元に SSG を行っています
現状のシステムでは記事が逐次更新される度に Vercel が GitHub の変更を読み取ってビルドを走らせてしまうのが少し良くないところです。
ただ記事の内容が変更されないとコミットしないようになっているので一応は無駄なビルドはしないようになっています
esa から GitHub にコミットを行う
実は esa は webhook を自分で書かなくても デフォルトで GitHub にコミットしてくれる機能があります。なので markdown の中身だけを貰いたい場合はその機能を使えばいいわけです。
ところで Astro のマークダウンを読み込む機能にはデフォルトで frontmatter を読み取ってくれるものがありますfrontmatterとは以下のようなものです。
markdown ファイルの先頭についてmarkdownファイルに関する説明を yml 形式で記述します。上にあげた frontmatter の例は esa からデフォルトの機能を使って GiHub にコミットした場合に追加されるものです。 これだけではブログを投稿してサイト内のみで有効なタグを持たせたり、関連するリンクを持たせたりするなどの付加情報が与えられません。
なので今回は esa で編集した markdown に frontmatter を生成するための情報をあらかじめ用意しておき、それを Astro のパース機能が読み取れる形に整形して、実際の記事の閲覧には不必要な情報を削除するためにバックエンドを構築しました。
今回なぜかフロントエンドのポートフォリオサイトなのにバックエンドが存在してしまった理由はこの機能を実現するためです。 無理をすれば Astro でページをレンダリングする際に markdown をパースして解析するのもできなくはないです。 しかし明らかにフロントエンドの領分を逸脱していると考えたためバックエンドとして切り分けました。 また GitHub にコミットされた markdown がそのままでは利用できないため 利便性が下がる問題があります。
esa の Generic Webhook を受け取って GitHub にコミットするバックエンド
レポジトリはこちら → https://github.com/kanakanho/esa-frontmatter-rewrite-push-github
レポジトリの中に esa の webhook の POST リクエストの型があるので似たようなことをしたい人の参考になると思います。
構成
バックエンドフレームワーク:Hono(TS)
デプロイ:Cloudflare Workers
その他ライブラリ:Biome , yaml , @octokit/rest
* @octokit/rest
は node 環境から GitHub へのコミットを行うためのライブラリです。
frontmatter に追加する情報の扱い
esa で 投稿用の記事を編集する際に先頭に以下のような コードブロック を追加しています。(backquoteはcodeblockの表示がくずれないために置いてあるだけ)
このコードブロックを API の中で解析し、frontmatter として追記します。そして必要になった yml のコードブロックは削除して、GitHub の release ブランチにコミットしています。
head の メタデータについて
このポートフォリオでは head のメタデータをページごとに動的に変更できるようになっています。これは生の Vite + React(SPA)ではできないので明確な Astro そして SSG の強みです。
Next.js の Metadata の型を参考に必要になるものをピックアップして、デフォルトの表示内容をグローバルに定義して、それぞれのページで変更が必要な部分のみを書き換えるという形を取りました。
Posts のそれぞれの記事のページではサイトそのものの OGP ではなくそれぞれの記事に関する OGP が指定できるので、SNS などで共有するときに便利になるので良いと思います。
各ページのスタイルについて
今回のサイトではできるだけ JS(TS) によるスタイルの変更を行わず、CSS(SCSS)だけで全ての表示が行われるように意識をしました。
javascriptを利用しているのはカラーモードの変更する場所のみです。(システム設定に基づく自動的なカラーモードの適応はCSSのみで対応済み)
ダークモードに対応したサイトは初めて作りました。想像していたよりも簡単にできたのですが、CSS変数の扱いが複雑になって実装のときにこんがらがって何も見えないページとかがたまに生まれて困惑しました。
flexbox ではなく グリッドレイアウト を基本としてレイアウトを行っています。これまでは基本的には flexbox を使っていて グリッドレイアウトを敬遠していたので意識的に使いました。
おかげで グリッドレイアウト の経験がだいぶ積めました。grid-row,grid-columの制御や grid-template の sub-grid による整列などいろんなことに慣れました。
擬似要素についても必要になったら使うというスタンスで利用しました。::before
や ::after
などの特性や綺麗に配置する方法が分かって満足しています。ただ html のタグに依存しない要素が css に記述されるのでこれまでの素直な css に比べると css をより綺麗に保つ工夫が必要になると感じました。
アニメーションについてもふんだんに取り入れてパソコンで触った時にいろんな表示要素が動く体験が得られると思うので色々触ってみてください。
終わりに
前回のポートフォリオを作ったのが約1年前でその頃は TypeScript が分からなくて React を触ってみたいからと Vite + React +JS で制作しました。その半年後に ShareLinks という別のプロダクトとして TS で再構築しているのですがどちらも SPA なのであんまり表示も早くないし、OGPも固定だしでもろもろ思うところがありました。
今回作り直すにあたって開発の難易度を下げるための妥協はやめてユーザーが触っていて体験のよいものにしようというのが大きくあって、その目的は SSG による静的なサイトの配信やカラーモードの切り替え、PCでの豊かなアニメーションやレスポンシブ対応によって達成できたのかな?と考えています。反面、実装の時間は長くなってしまいましたが…。
また esa によるサイトの表示内容の更新は絶対にやりたいことの1つとしてありました。前のHUGOが結構扱いずらいと感じていたのもあって、今回の自動的にコミットしてデプロイが走るシステムというのはログを見ているだけで気持ちがいいし良かったと感じています。ただ画像なども esa の AWS というか S3 に頼ってしまっているので、それは今後どうにかしないといけないと思います。esa がなくなったら本当の意味で立ち行かないシステムになってしまう。
しばらくフロントから離れていたせいで様々なものが新しく移り変わっていて、キャッチアップと技術選定にも時間がかかってしまいました。
ともあれ一旦完成させて、自動デプロイが回るようになって、システムとしての運用ができるようになったので満足しています。
以降はとても長くなってしまったのでおまけです。何を考えてポートフォリオを作ったのかを詳しく書いてあります。
より詳しいポートフォリオ作成の際の構想
以下の手順でポートフォリオサイトの構想を練りました
- ポートフォリオをなぜ作るのか
- 達成しなければならない条件の定義
- 条件を満たすための手法と使用技術の選定
- 画面構成の決定
- コンポーネントのデザイン
以下に順番に考えていたことを記述していきます
1. ポートフォリオをなぜ作るのか
- 自分のこれまでの活動を宣伝するため
2. 達成しなければならない条件
- ネットワークさえあれば誰でもどんな環境でも見れること
- 特別なアプリケーションやログインを要求しない
- 快適に閲覧ができること
- レンダリングが高速
- 軽量
- 1つのサイトで完結
- 自己紹介や投稿などで別のサイトにしない
- 快適に更新ができること
- 記事の投稿に際して、いちいちテキストエディタを開いて markdown を編集してGitHubにコミットするのはめんどくさい
3. 条件を満たすための手法と使用技術の選定
web framework
- Astro
- React (コンポーネントの記述のために利用)
- vite(Astroが内部的に利用している)
Linter & Formatter
- Biome とその拡張機能
- TS,TSX,JS の Linter & Formatter として利用
- Astro の Linter として利用
- Prettier とその拡張機能
- SCSS,Astro の Formatter として利用
Dev
- Git / GitHub
- バージョン管理のために利用
- Storybook
- コンポーネントの表示の確認のために利用
Deploy
- Vercel
- Vercel が一番ダッシュボードの扱いに慣れているため採用
- Cloudflare Pages とか Github Pages などが選択肢にあった
- Cloudflare Pages はこれまで触ったことがないのと、特段採用する理由が思いつかなかった
- Github Pages は yml を書く手間をわざわざ取りたくなかったので不採用
Write Posts
- https://esa.io
- markdown が書きやすい(自動補正とプレビューが優秀)ため採用
- 変更内容を webhook で自作のバックエンドに飛ばせるため採用
backend esa の webhook から GitHub へのコミットを行うために作成 esa の GitHub への webhook では任意の frontmatter が指定できないためにバックエンドを作った
- hono
- 一番わかりやすく書ける Node.js のバックエンドフレームワークだと思うので採用
- @octokit/rest
- バックエンドから GitHub にコミットを行うために使用したライブラリ
- Cloudflare Workers
- デプロイ先として利用
- wrangler があるおかげでデプロイが楽
- ただ環境変数の扱いが微妙
Analytics
- Google Analytics
- これまで使ってこなかったため、採用して検証する
Design
- Figma
- 能力的には Adobe illustrator も使えるが、オンライン上で編集して他の人と共有ができる Figma の方が一般的な web開発では都合がいいと思ったので採用
- オートレイアウトの機能が illustrator ではやりずらい グリッドレイアウト や flexbox の検証ができる点も採用した理由の1つ
Another ドメインはcloudflareで取得して管理しています
> ネットワークさえあれば誰でもどんな環境でも見れること
この条件を満たすかつ私のスキル的にも自己を表現するのに最も適した媒体が web なので web サイトとして公開するのは早めに決まりました。
> 快適に閲覧ができること
以前のサイトは Vite + React で書かれていたため、webサイトを開くとクライアント側でレンダリングが行われるため、webページを開いてから最初に表示されるまでのタイムラグがありました。これでは見る側に優しくないのでベースとして静的なサイトを構築と決めました。また以前のサイトでは画像が無駄に大きくて読み込みに時間がかかる問題があったため、適度な解像度の画像が用意できるようにしました。
元々の記事の投稿は HUGO で行っていて、ポートフォリオとは別のサイトかつ別のフレームワークで動いていたので、利便性に欠いていました。それを回避するために記事の閲覧も行えるようにしようと決めた。
> 快適に更新ができること
以前の記事の投稿には HUGO を利用していたため、記事を更新するためにはパソコンでプロジェクトを開いて markdown を編集する必要があり手間が大きかった。特定の端末に依存しない環境で記事が書けるようになるととても便利になるのでその方法を考えた。
esa で変更した内容をhono で構築して Cloudflare Workers でデプロイしたバックエンドに esa が持つ webhook の機能でリクエストを飛ばして、frontmatter を追加して Markdown 形式のファイルとして Github にコミットしている。
4. 画面設計の決定
テキストベースで表示内容を決めてから それぞれのコンポーネントを Figma で設計した 今回はあまり厳密なレイアウトを Figma で決めるのはしなかった
Home
メインとなるページ
必要なもの
- ざっくりと私を説明するトップページ
- 私に連絡ができるものの提示
About me
自分の詳細な紹介をするページ
必要なもの
- これまでの軌跡
- 扱ってきた技術
works
これまで作ってきたものをまとめたページ
必要なもの
- これまでのポートフォリオサイト の Products に相当するもの
Posts
活動履歴を記事としてまとめたページ
必要なもの
- これまで参加してきたイベント、開発してきたものについての記事
- これまでのブログサイトに相当するもの
5. コンポーネントのデザイン
Figma 作った。オートレイアウトを使って勝手に要素が配置されるのを意識しました。またバリアブルも初めて使ったのですが、積極的に利用して個々の要素に対して後から変更する手間がなくなってとても便利でした。