外部JSゼロ・爆速・プライバシー配慮の自作コンポーネントをブログに追加した話
更新日:
作成日:
どーも、ちょりんだです。
なぜ「外部JSゼロ」にこだわったのか
モダンなWeb開発では、ReactやVue、あるいは各種UIライブラリの導入が当たり前になっています。しかし、個人ブログのような小規模サイトでそれらを導入すると、以下の課題が生じます。
- バンドルサイズの肥大化:使わない機能まで読み込まれる
- プライバシー懸念:CDN経由の外部スクリプトはユーザーの行動を追跡する可能性がある
- 表示速度の劣化:追加のHTTPリクエストとJS実行コスト
- メンテナンス負担:ライブラリアップデートや脆弱性対応
特にブログは「読む」ことが主目的です。UIの派手さより、コンテンツが素早く表示されることが最優先です。
実装したコンポーネント群
高優先:読者体験を直結する機能
⏱️ 読了時間表示
// 文字数÷600字/分で計算(日本語の平均読書速度)
const minutes = Math.max(1, Math.ceil(charCount / 600));
- ビルド時生成:Astroのビルドプロセスで計算
- JSゼロ:サーバーサイドで完結
- 表示例:「約3分で読めます」
📑 目次(ToC)
- 見出しから自動生成:h2/h3を抽出
- スクロール追従:CSS
scroll-marginでスムーズ移動 - レスポンシブ:モバイルでも見やすいレイアウト
📋 コードコピーボタン
// インラインJSで完結(10行程度)
navigator.clipboard.writeText(code).then(() => {
btn.textContent = 'Copied!';
setTimeout(() => (btn.textContent = 'Copy'), 2000);
});
🔗 SNSシェアボタン
- 外部JSなし:
<a>タグとURLパラメータのみ - 対応サービス:X, はてなブックマーク, LINE
- プライバシー安全:外部タグやトラッキングなし
中優先:UXを向上させる機能
🌙 ダークモード
// localStorage + prefers-color-scheme
const theme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.classList.toggle('dark', theme === 'dark');
- システム設定尊重:
prefers-color-scheme - 状態永続化:
localStorage - FOUC対策:インラインスクリプトで先読み
📊 読了プログレスバー
// パフォーマンス最適化
window.addEventListener('scroll', updateProgress, { passive: true });
- 固定表示:ページ最上部
- 滑らかなアニメーション:CSS
transition - 軽量:5行のJSで実装
🔍 全文検索
- Pagefind:ビルド時に検索インデックス生成
- 外部通信なし:クライアントサイドで完結
- 日本語対応:形態素解析なしでも実用レベル
📄 OGPメタタグ
- 自動生成:Astroのビルド時
- Twitter Card対応:
summary_large_image - URL正規化:
canonicalタグ
低優先:あると嬉しい機能
⬆️ トップに戻るボタン
- 表示条件:300pxスクロール時
- smooth scroll:
scrollTo({ behavior: 'smooth' }) - アクセシビリティ:
aria-label付き
⬅️➡️ 前後の記事ナビ
- 静的生成:ビルド時に隣接記事を計算
- レスポンシブ:スマホで縦並び
- タイトル省略:2行まで表示
技術的工夫
CSS変数とTailwindの組み合わせ
/* ダークモード対応 */
@custom-variant dark (&:where(.dark, .dark *));
/* コンポーネント */
.bg-white dark:bg-slate-800
インラインJSの活用
- 小規模な処理:イベントリスナー程度
- FOUC対策:
<script is:inline>で先実行 - パフォーマンス:追加のHTTPリクエストなし
ビルド時最適化
- 静的生成:可能な限りSSG
- インデックス生成:Pagefind
- 画像最適化:将来のOGP自動生成に備え
パフォーマンス計測
Lighthouseスコア(改善前→改善後)
- Performance: 85→98
- Accessibility: 92→100
- Best Practices: 87→98
- SEO: 95→100
バンドルサイズ
- JS: 0KB(自作コンポーネントのみ)
- CSS: 12KB(Tailwind、purge済み)
- 合計: 約45KB(画像除く)
まとめ
外部ライブラリに頼らず、必要な機能だけを自作することで、以下のメリットが得られました。
- 爆速表示:不要なJSの読み込みなし
- プライバシー配慮:外部スクリプトやトラッキングなし
- メンテナンス性:コード量が少なく、理解しやすい
- 学びの機会:Web標準技術の深い理解
もちろん、大規模なアプリケーションではReactやVueの価値は絶大です。しかし、個人ブログのような小規模サイトでは、「シンプルであること」が最強の機能だと改めて実感しました。
リファクタリングはコードだけでなく、アーキテクチャ選択にも適用できる。最小限の依存で最大の価値を。
今後もこのブログを通じて、技術選定の思考プロセスを共有していければと思います。