kanakanho / しばいぬ

About me

Works

Posts

Contact / Links

ポートフォリオサイトを新たに作りました

latest

portfolio-mini.jpeg (414.7 kB)

ポートフォリオサイトを新たに制作しました。

はじめに

夏休み期間中に以前作ったポートフォリオサイトよりもモダンでおしゃれなポートフォリオサイトを作りたいと思い立って制作しました。 また制作に当たって各要件を分解してそれぞれの目標を達成できるように、技術構成や画面構成を練りました。

技術構成

web framework

Linter & Formatter

Dev

Deploy

Write Posts

backend

Analytics

技術構成に関する簡単な説明

もっと詳しく知りたい方は #より詳しいポートフォリオ作成の際の構想 を参照してください

Astro を採用した理由

今回は静的なサイトを作りたかったので Vite + React の選択肢はありませんでした。次に候補に上がったのが Next.js でしたが、SSR をしないためフレームワークとして大きすぎると思ったため不採用に。
SSG ができて css module と scss と react と storybook が使えるフレームワークで必要十分だと感じたため採用しました。

実装してみて SSG の快適さを身に沁みて感じています。これまでのポートフォリオに比べて本当に軽くなって、表示までの時間が短くなっていて嬉しいです。

Biome を採用した理由

https://biomejs.dev/

応援しているから

hono を採用した理由

一番書きやすいと感じるバックエンドフレームワークであるため
また Cloudflare Workers でのデプロイの手間がほとんどかからないかつ、ログも確認しやすいため

esa を採用した理由

一番使いやすいオンラインの markdown 編集ツールであると感じるため
かつ webhook で markdown の変更内容をバックエンドで利用できるため

この記事もesaを使って書いています
こんな素晴らしいサービスを学生には無料で使わせてくださるesaの方には感謝しかないです

Posts と Works の内容を自動で更新するシステムの構築

一度ページを見て確認して欲しいのですが、 PostsWorks のそれぞれのページはハードコーディーングを行っているわけではありません

Release ブランチ の /posts ディレクトリにコミットされる Markdown ファイル の中身を元に SSG を行っています

現状のシステムでは記事が逐次更新される度に Vercel が GitHub の変更を読み取ってビルドを走らせてしまうのが少し良くないところです。
ただ記事の内容が変更されないとコミットしないようになっているので一応は無駄なビルドはしないようになっています

esa から GitHub にコミットを行う

実は esa は webhook を自分で書かなくても デフォルトで GitHub にコミットしてくれる機能があります。なので markdown の中身だけを貰いたい場合はその機能を使えばいいわけです。

ところで Astro のマークダウンを読み込む機能にはデフォルトで frontmatter を読み取ってくれるものがありますfrontmatterとは以下のようなものです。

esaのGitHubへのwebhookで自動的に追加されるfrontmatter.md
---
title: 記事のタイトル
category: posts/latest
tags:
created_at: '2024-01-01T00:00:00+09:00'
updated_at: '2024-01-01T00:00:00+09:00'
published: true
number: 1
---
<!--more-->

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の表示がくずれないために置いてあるだけ)

.md
\```yml title=".yml"
isActive: false
tags:
description:
repository:
youtube:
website:
image:
worksDisplay: false
worksTitle:
worksDescription:
worksImage:
\```
<!--more-->

このコードブロックを 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. 達成しなければならない条件の定義
  3. 条件を満たすための手法と使用技術の選定
  4. 画面構成の決定
  5. コンポーネントのデザイン

以下に順番に考えていたことを記述していきます

1. ポートフォリオをなぜ作るのか

2. 達成しなければならない条件

3. 条件を満たすための手法と使用技術の選定

web framework

Linter & Formatter

Dev

Deploy

Write Posts

backend esa の webhook から GitHub へのコミットを行うために作成 esa の GitHub への webhook では任意の frontmatter が指定できないためにバックエンドを作った

Analytics

Design

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

これまで作ってきたものをまとめたページ

必要なもの

Posts

活動履歴を記事としてまとめたページ

必要なもの

5. コンポーネントのデザイン

Figma 作った。オートレイアウトを使って勝手に要素が配置されるのを意識しました。またバリアブルも初めて使ったのですが、積極的に利用して個々の要素に対して後から変更する手間がなくなってとても便利でした。

Postsに戻る