フロントエンド・Next.jsの用語
実際に画面を組み立てて表示する側の言葉。速さと使いやすさに関わる。
それぞれ「なぜそれがあるのか」と「つまずきやすい点」まで書いています。実際にこのサイトを作る中で出てきた具体例も入れました。
アクセシビリティ / IntersectionObserver / カスタムイベント / 型定義の自動生成 / キャッシュ / コードモッド / CSS変数 / sticky / z-index / デプロイ / ハイドレーション / visibilitychange / ビューポート / ビルド / フォールバック / prefers-reduced-motion / requestAnimationFrame / ResizeObserver / レスポンシブ / レンダリング / ISR / App Router / alt属性 / Client Component / Server Component / TypeScript / Tailwind CSS / localStorage
アクセシビリティ(あくせしびりてぃ)
どんな条件の人にも使えるように作ること。読み上げ、キーボード操作、色の見え方など。
どんな条件の人でも使える状態にすることです。視覚に障害がある人、マウスを使えない人だけの話ではありません。
対象は広い
片手がふさがっている、屋外で画面が見えにくい、音を出せない場所にいる、通信が遅い。誰でも一時的に「使いにくい条件」に入ります。
すぐできること
画像に説明文(alt属性)を付ける。見出しを大きさではなく意味の順番で使う。リンクの文言を「こちら」ではなく行き先が分かる言葉にする。色だけで情報を伝えない。
意外な効果
これらは検索エンジンにも効きます。読み上げソフトと検索エンジンは、どちらも見た目ではなく構造を読んでいるからです。装飾ではなく意味で作られたページは、両方に伝わります。
IntersectionObserver(いんたーせくしょんおぶざーばー)
要素が画面に入った・出たことを、ブラウザ側で判定して教えてくれる仕組み。
ある要素が画面に入ったかを、ブラウザが判定して教えてくれる仕組みです。日本語では「交差監視」と訳されます。
自分で計算しない理由
同じことは、スクロールのたびに全要素の位置を測っても実現できます。しかしスクロールは1回の操作で何十回も発生し、要素が増えるほど計算量が積み上がります。
この仕組みはブラウザの内側で判定されるため、監視する要素が増えても負荷がほとんど変わりません。
使いどころ
いま読んでいる見出しの追跡、画像の遅延読み込み、「ここまで到達した」の検知。位置そのものではなく、境界をまたいだ瞬間が知りたいときに向いています。
関連記事: 読む体験をつくる — 目次の自動生成から読了状態の保存まで
カスタムイベント(かすたむいべんと)
自分で名前を決めて発行できるイベント。離れた部品どうしの連絡に使う。
クリックやスクロールのような既定のものとは別に、自分で名前を決めて発行できるイベントです。
使いどころ
画面上で離れた場所にある部品どうしが、同じできごとを知る必要があるとき。共通の親から状態を配る作りにすると、間にある部品まで巻き込んで作り替えることになります。
記録する側: 「読了した」と投げる
表示する側: 「読了した」を受け取って表示を変える
お互いを直接知らないまま、できごとだけを共有できます。
注意
便利な反面、誰が投げて誰が受けているのかがコードから追いにくくなります。数が増えると流れを見失うので、使う場面を絞るほうが安全です。
型定義の自動生成(かたていぎのじどうせいせい)
APIの仕様から、扱うデータの型を機械的に作り出す仕組み。codegenと呼ばれる。
APIから返ってくるデータの形を、仕様書から機械的に型として書き出す仕組みです。GraphQLでは graphql-codegen がよく使われます。
何が嬉しいのか
手で型を書くと、APIが変わったときに書き換え漏れが起きます。自動生成なら、実際の仕様と型が必ず一致します。存在しない項目を参照していれば、その場で気づけます。
引き換えに背負うもの
問い合わせ内容を1文字でも変えたら、型を作り直す必要があります。そして作り直しには、APIサーバーに接続して仕様を読む処理が必要です。
つまり、APIに繋がらない環境では、問い合わせを1つ足すこともできません。便利さと引き換えに、この制約を受け取ることになります。
影響の小さい箇所では、あえて自動生成を使わず手で型を書く、という判断もあり得ます。仕組みの利点は、全部に適用しなくてもよいという考え方です。
キャッシュ(きゃっしゅ)
一度取得した結果を保存しておき、次回は再利用する仕組み。
一度取得した結果を保存しておき、次に同じものが必要になったとき、取りに行かずに使い回す仕組みです。
どこにでもある
ブラウザ、CDN、サーバー、DNS、アプリの中。1回の表示に、いくつものキャッシュが関わっています。これが「直したのに反映されない」の原因を分かりにくくします。
付き合い方
確認のときは、どの層のキャッシュを見ているのかを意識する必要があります。ブラウザの再読み込みで直るならブラウザ側、それでも古いならその先です。
キャッシュを避けて取得する方法(URLに毎回違う文字列を付ける、など)を1つ覚えておくと、切り分けが速くなります。
設計上の注意
キャッシュは効かせる場所を間違えると意味がありません。たとえばNext.jsの標準的なキャッシュはGET通信にしか効かないため、POSTで問い合わせる仕組みでは素通りします。
関連記事: 速くしたら、壊れた — 表示1.7秒を0.03秒にするまでと、その代償
コードモッド(こーどもっど)
コードを機械的に書き換えるツール。バージョン移行の定型作業に使う。
codemod。決まったパターンのコードを、機械的に書き換えるツールです。ライブラリのメジャーバージョン更新に伴う定型的な修正に使われます。
何が嬉しいのか
数十ファイルにまたがる同じ書き換えを、見落としなく一度に行えます。手作業だと必ずどこかを飛ばします。
過信してはいけない点
「エラー0件」は「全部やった」ではありません。ツールが認識できなかった書き方は、静かに素通りします。変更されたファイル数と、自分が想定していた箇所の数が合っているかは、自分で確かめる必要があります。
また、ツールは一般的に安全な側へ倒します。そのプロジェクトには不要な設定を、将来のために先回りして追加してくることがあります。出力をそのまま受け取らず、読んでから採用するかを決めるべきです。
CSS変数(しーえすえすへんすう)
CSSの中で使い回せる値の入れ物。JavaScriptから書き換えることもできる。
CSSの中で値に名前を付けて使い回す仕組みです。カスタムプロパティとも呼びます。
:root { --header-offset: 3.5rem; }
.toc { top: var(--header-offset); }
ただの定数ではない
ここが普通の変数と違う点です。JavaScriptから書き換えると、その値を使っている場所がすべて追従します。
離れた場所にある要素どうしで状態を合わせたいとき、部品から部品へ値を渡していく代わりに、片方が書いて、もう片方が読むという形にできます。お互いを直接知らなくて済みます。
つまずきやすい点
書き換えたつもりで効かない場合、宣言した場所より内側で上書きされていることがあります。CSS変数は、指定した要素とその子孫にだけ効きます。
sticky(すてぃっきー)
スクロールしてある位置まで来たら、そこで貼り付いて動かなくなる指定。
CSSの position: sticky のことです。普段は普通に流れていて、決めた位置まで来たらそこで止まるという動きをします。目次やヘッダーを画面に残しておきたいときに使います。
fixed との違い
fixed は最初から画面に固定されます。sticky はスクロールしてくるまでは普通の位置にいます。記事の途中にある目次を、そこまで読み進めたら貼り付ける、といったことができます。
つまずきやすい点
効く範囲は、親要素の中だけです。親の領域を過ぎると一緒に流れて消えます。これは制限ではなく便利な性質で、記事本文を親にしておけば、記事が終わったところで目次も自然に消えてくれます。
もうひとつ、親のどこかに overflow: hidden があると効きません。指定は正しいのに貼り付かない、という場合はここを疑います。エラーは出ないので気づきにくい部分です。
関連記事: 読む体験をつくる — 目次の自動生成から読了状態の保存まで
z-index(ぜっといんでっくす)
要素が重なったとき、どちらを手前に表示するかを決める数値。
要素が重なったときの前後関係を決める数値です。大きいほうが手前に来ます。
なぜ必要なのか
貼り付く要素(ヘッダー、目次、ボタン)が増えると、必ずどこかで重なります。指定しないと「HTMLに後から書いたほうが手前」という既定の順番になり、意図とずれます。
実務での決め方
思いついた数字を書くと、あとで「もっと手前に出したい」となるたびに数字が膨らみます。先に段を決めておくほうが管理できます。
50 ヘッダー(最前面)
40 トップへ戻るボタン
30 記事内の追従目次
数字そのものに意味はなく、大小関係だけが意味を持ちます。間を空けておくと、後から途中に差し込めます。
デプロイ(でぷろい)
ビルドした成果物を、実際に公開されるサーバーへ配置して動く状態にすること。
ビルドしてできたものを実際のサーバーに配置し、公開状態にすることです。「本番に出す」とほぼ同じ意味で使われます。
いまの一般的な流れ
コードをリポジトリにpushすると、自動でビルドとデプロイが走る構成が主流です。人が手でファイルを転送する場面は減りました。
気をつけたいこと
自動化されている分、間違いもそのまま本番に届きます。手元での確認を挟まずにマージすると、通るかどうかは本番のビルドが動いてから分かる、という状態になります。
多くのサービスには、本番とは別のプレビュー環境を作る機能があります。ブランチをpushすると確認用のURLができるので、本番と同じビルドで動作を確かめてから公開できます。
関連記事: ローカルのサイトを本番公開するまでにハマった話
ハイドレーション(はいどれーしょん)
サーバーが作ったHTMLに、ブラウザ側で動きを結び付ける処理。
サーバーが先に作って送ったHTMLに対して、ブラウザ側であとから動きを結び付ける処理のことです。「水を与える」という語感から来ています。
何のためにあるのか
HTMLを先に送れば、JavaScriptの読み込みを待たずに文字が表示されます。しかしそのままではボタンを押しても反応しません。あとから動きを付けることで、表示の速さと、操作できることの両立を狙っています。
つまずきやすい点
サーバー側で作ったHTMLと、ブラウザ側で作り直した結果が食い違うと警告が出ます。
よくある原因は、サーバーには存在しないものを最初の描画で使ってしまうことです。ブラウザにしか無い保存領域や、現在時刻、乱数などが該当します。画面に出たあとで読み直す形にすると避けられます。
関連記事: 読む体験をつくる — 目次の自動生成から読了状態の保存まで
visibilitychange(びじびりてぃちぇんじ)
ページが見えている状態になった/隠れたことを知らせるイベント。
そのページがいま見えているかどうかが変わったときに発生するイベントです。別のタブに切り替えた、ウィンドウを最小化した、といった場面で起きます。
なぜ必要なのか
「ページを開いていた時間」と「実際に見ていた時間」は違います。タブを開いたまま放置した時間まで数えると、滞在時間はいくらでも伸びます。
見えている → 数える
隠れている → 止める
戻ってきた → また数える
こうすると、席を外して戻ってきた人が不利にならず、開きっぱなしの人が有利にもなりません。
つまずきやすい点
ページを閉じるときには、必ずしも発生しません。最後に状態を保存したい場合は、このイベントだけに頼らない作りが要ります。
ビューポート(びゅーぽーと)
いま画面に見えている範囲のこと。ページ全体ではなく、窓の大きさ。
いま画面に見えている範囲のことです。ページ全体を1枚の長い紙とすると、ビューポートはその上を移動する窓にあたります。
なぜ区別が要るのか
「ページの高さ」と「見えている高さ」は別物です。ここを混同すると、位置の計算がずれます。
ページ全体の高さ 7,600px ← 紙の長さ
ビューポートの高さ 800px ← 窓の大きさ
スクロールできる量 6,800px ← 紙 - 窓
つまずきやすい点
スマートフォンでは、アドレスバーの出入りでビューポートの高さが変わります。スクロールしただけで数値が変わるので、最初に測った値を持ち続けると、途中からずれます。
ビルド(びるど)
書いたコードを、実際に配信できる形に変換する処理。
人間が書いたコードを、ブラウザやサーバーが実行できる形に変換する処理です。
何をしているのか
TypeScriptをJavaScriptに変換したり、複数のファイルを1つにまとめたり、不要な部分を削ったりします。書きやすい形と、動かすのに適した形は違うため、この工程が必要になります。
知っておくべきこと
ビルドが通ることは、「矛盾が無い」ことの証明です。「意図した通りに動く」ことの証明ではありません。
実際に、変更が丸ごと消えていてもビルドは正常に通ります。何も変えていないコードは、当然のように矛盾しないからです。緑色の結果を「直っている」と読み替えないことが大事です。
関連記事: ローカルのサイトを本番公開するまでにハマった話
フォールバック(ふぉーるばっく)
本来の処理が失敗したときに、代わりに使う手段や値。
本来やりたい処理が失敗したときに、代わりに実行する内容のことです。「保険」に近い言葉です。
なぜ必要なのか
外部のサーバーは、必ずいつか応答しません。混雑、障害、通信の一時的な失敗。相手が「たまに失敗する」前提で作るほうが、現実に合っています。
設計のコツ
大事なのは、何を諦めて何を守るかを決めておくことです。
たとえばサイトマップを作る処理で、記事一覧の取得に失敗したとします。ここで例外を外に出すとサイトマップ自体がエラーになり、固定ページの分すら渡せません。記事が載っていないサイトマップは不完全ですが、存在しないよりは役に立ちます。
ただし、握りつぶすなら記録を残すこと。静かに失敗し続ける仕組みは、壊れていることに誰も気づけません。
関連記事: 速くしたら、壊れた — 表示1.7秒を0.03秒にするまでと、その代償
prefers-reduced-motion(ぷりふぁーずりでゅーすともーしょん)
「画面の動きを減らす」という利用者側の設定を、サイトから読み取るための指定。
端末の「視差効果を減らす」「動きを減らす」といった設定を、サイト側から読み取るための指定です。
なぜ用意されているのか
画面が滑らかに動くことは、全員にとって快適とは限りません。前庭障害のある方では、大きな動きが吐き気やめまいを引き起こすことがあります。
OSにはその設定があり、利用者はすでに意思表示をしています。サイト側は、それを無視しないだけで済みます。
実装での扱い
設定されているときは、滑らかな移動をやめて一瞬で移動させる、大きなアニメーションを省く、といった対応をします。機能そのものを取り上げる必要はありません。動きの量だけを減らします。
requestAnimationFrame(りくえすとあにめーしょんふれーむ)
次に画面が描き直されるタイミングで処理を実行する仕組み。間引きに使う。
次に画面が描き直されるタイミングに合わせて処理を実行する仕組みです。
間引きに使う
スクロールイベントは、1回の操作で何十回も飛んできます。そのたびに位置を計算しても、画面が描き直されるのは1秒に60回程度なので、それ以上の計算は表示に反映されません。
スクロール発生 → すでに予約済みなら何もしない
→ 未予約なら「次の描画時に計算」を予約
結果として、計算は描画1回につき1回に収まります。
タイマーとの違い
時間で区切る方法(0.1秒ごとなど)もありますが、描画のタイミングとずれると、動きがかすかにぎこちなくなります。描画に合わせるほうが、見た目が滑らかになります。
ResizeObserver(りさいずおぶざーばー)
要素の大きさが変わったことを教えてくれる仕組み。画面サイズの変化とは別。
要素の大きさが変わったことを教えてくれる仕組みです。
画面サイズの変化とは別物
ここが要点です。resize イベントは画面(ウィンドウ)の大きさが変わったときだけ発生します。
しかし要素の高さは、画面サイズが変わらなくても動きます。画像が後から読み込まれる、折りたたみを開く、フォントが差し替わる——いずれも resize は起きません。
読み込み時に測った高さを持ち続けると、あとから中身が伸びた瞬間にずれます。ずれてもエラーは出ないので、計算結果だけが静かに間違い続けます。
使いどころ
要素の高さを分母にして割合を出すとき。中身が変わりうる場所を測っているなら、この仕組みで測り直す必要があります。
レスポンシブ(れすぽんしぶ)
画面の幅に応じて、レイアウトを切り替える作り方。
画面の幅に応じてレイアウトを変える作り方です。同じHTMLのまま、スマホでは1列、PCでは2列、といった切り替えを行います。
考え方のコツ
「縮める」ではなく、「その画面で何が余っていて、何が足りないか」で考えると設計しやすくなります。
PCには横の余白があるので、目次を右側に置いても本文は削られません。スマホには横の余白が無いので、同じものを置けば本文の面積を奪います。同じ機能でも、払う代償が違います。
実務での注意
スマホでは、画面の下端もブラウザのUIに取られています。実際に本文が見えている範囲は、数字より狭いと考えたほうが実態に合います。
場所が足りないときは、消す前に並べ替えを試す価値があります。縦に積んだものを横一列にするだけで、情報を減らさずに高さを半分にできることがあります。
レンダリング(れんだりんぐ)
データからHTMLを組み立てること。どこで組み立てるかで方式が分かれる。
データを元に実際に表示されるHTMLを組み立てる処理です。「どこで組み立てるか」で方式が分かれます。
| 方式 | いつ組み立てるか | 特徴 |
|---|---|---|
| SSG | あらかじめ(ビルド時) | 最速。更新には再ビルドが要る |
| SSR | アクセスのたびにサーバーで | 常に最新。待ち時間が出る |
| CSR | ブラウザの中で | 操作は軽快。初回表示が遅い |
| ISR | あらかじめ+定期的に作り直す | 速さと新しさの折衷 |
選び方
更新の頻度と、待たせてよい時間で決まります。ほとんど変わらない内容なら事前に作っておけばよく、常に最新でなければ困る内容ならその都度作る必要があります。
関連記事: なぜこの構成にしたのか — ヘッドレスWordPress + Next.js の技術選定
ISR(アイエスアール)
事前に作ったページを配信しつつ、一定時間ごとに裏側で作り直す方式。
Incremental Static Regeneration の略。ページを事前に作って配信し、指定した時間が過ぎたら裏側で静かに作り直す仕組みです。
何が嬉しいのか
訪問者は、すでに出来上がっているページを受け取るので待ちません。アクセスのたびにデータベースへ問い合わせる必要がないためです。
それでいて、内容が更新されれば時間の経過とともに反映されます。全ページを作り直す必要もありません。
引き換えに受け入れること
更新が即座には反映されません。設定した時間(たとえば300秒)のあいだは、古い内容が配信され続けます。
この性質は、確認のときに混乱の元になります。「直したのに変わらない」の多くは、この待ち時間です。キャッシュを避けて確認する方法を知っておくと、無駄に悩まずに済みます。
関連記事: 速くしたら、壊れた — 表示1.7秒を0.03秒にするまでと、その代償
App Router(アップルーター)
Next.jsの新しいルーティング方式。フォルダ構成がそのままURLになる。
Next.jsにおけるページの置き方とURLの決まり方の新しい方式です。app/ フォルダの中の構成が、そのままURLになります。
app/blog/page.tsx → /blog
app/blog/[slug]/page.tsx → /blog/任意の文字列
特徴
フォルダ名を角括弧で囲むと、可変の部分を表せます。記事ごとにファイルを作らなくても、1つの雛形で全記事に対応できます。
また、layout.tsx を置くと、その配下すべてに共通の枠を適用できます。ヘッダーやフッター、あるいは特定の範囲だけに出したい要素を、1ファイルで管理できます。
知っておくべきこと
App Routerでは、既定ですべてがサーバー側で動きます。ブラウザでの操作が必要な部分だけを明示的に指定する、という考え方に変わりました。以前の方式とは前提が逆になっています。
alt属性(オルトぞくせい)
画像の内容を説明する文字。画像が表示できないときや、読み上げに使われる。
画像に付ける説明の文字です。画像が読み込めなかったときに代わりに表示され、読み上げソフトはこれを読みます。
書き方の目安
「その画像が伝えている内容」を書きます。ファイル名や「画像」といった語は不要です。
× alt="image01.png"
× alt="画像"
○ alt="DNSの問い合わせが3段階で行われる流れ図"
空にすべき場合もある
装飾のためだけの画像には、あえて空(alt="")にします。意味を持たない画像を読み上げられても、邪魔になるだけだからです。
属性そのものを省くと、読み上げソフトがファイル名を読んでしまうことがあります。「書かない」と「空にする」は違います。
Client Component(クライアントコンポーネント)
ブラウザ側でも動く部品。クリックへの反応や、ブラウザ固有の情報を扱える。
ブラウザ側でも実行される部品です。Next.jsではファイルの先頭に "use client" と書いて指定します。
いつ必要になるのか
クリックや入力への反応、スクロール量の取得、ブラウザに保存した値の読み書き。その人のブラウザの中でしか分からないことを扱うときです。
使いすぎないほうがよい理由
指定した部品のコードはブラウザに送られます。増えるほど読み込みが重くなります。
コツは、ページ全体ではなく、動きが必要な部分だけを切り出すことです。たとえば記事ページ全体をブラウザ側にする必要はなく、進捗バーの部分だけをそうすれば足ります。
関連記事: 読む体験をつくる — 目次の自動生成から読了状態の保存まで
Server Component(サーバーコンポーネント)
サーバー側だけで実行される部品。ブラウザにコードが送られないため軽い。
サーバー側だけで実行され、結果のHTMLだけがブラウザに届く部品です。Next.jsのApp Routerでは、これが既定になっています。
何が嬉しいのか
部品そのもののコードがブラウザに送られません。そのぶん読み込むデータが減り、表示が速くなります。
また、データベースへの接続情報のような見せてはいけない値を安全に扱えます。ブラウザに届かないからです。
できないこと
クリックへの反応や、ブラウザにしかない情報(画面幅、保存された設定など)は扱えません。サーバーは、その人のブラウザの中を知らないためです。
そうした処理が必要な部分だけを、Client Componentとして切り出します。ページ全体ではなく、必要な部品だけをブラウザ側にするのが基本の考え方です。
関連記事: 読む体験をつくる — 目次の自動生成から読了状態の保存まで
TypeScript(タイプスクリプト)
JavaScriptに型の仕組みを足した言語。実行前に間違いを見つけられる。
JavaScriptに「この値は文字列」「この値は数値」といった型の情報を加えた言語です。最終的にはJavaScriptに変換されて動きます。
何が嬉しいのか
実行する前に間違いが見つかります。存在しない項目を参照している、数値を期待している場所に文字列を渡している、といった間違いをビルド時に指摘してくれます。
また、エディタが補完してくれるようになります。何が使えるのかを覚えていなくても書けます。
誤解しやすい点
型が通ることは、「正しく動く」ことを意味しません。「矛盾していない」ことを示すだけです。計算式が間違っていても、型が合っていれば通ります。
Tailwind CSS(テイルウィンド シーエスエス)
あらかじめ用意された細かいクラスを組み合わせて見た目を作るCSSの仕組み。
text-sm(小さい文字)、mt-4(上に余白)のような用意された細かいクラスを組み合わせて見た目を作る仕組みです。
何が変わるのか
従来は、CSSファイルに自分で名前を付けたルールを書いていました。この方式では、名前を考える必要がなく、HTMLを見ればそこの見た目が分かります。
使われなくなったCSSが残り続ける、という問題も起きにくくなります。
知っておくと効く仕組み
クラス名は設定ファイルにある値の表を参照しています。つまり表のほうを書き換えれば、そのクラスを使っている全箇所が一度に変わります。
「サイト全体の角丸を控えめにしたい」といった調整を、各所を回らずに1か所で済ませられるのは、この仕組みのおかげです。散らばったものを1つずつ直すと、必ず漏れます。
localStorage(ローカルストレージ)
ブラウザにデータを保存する仕組み。サーバーには送られず、その端末にだけ残る。
ブラウザの中にデータを保存する仕組みです。サーバーには送られず、その端末のそのブラウザにだけ残ります。
Cookieとの違い
Cookieは通信のたびに自動でサーバーへ送られますが、localStorageは送られません。そのぶん通信は軽くなりますが、サーバー側からは中身が分かりません。
また、有効期限がなく、明示的に消すまで残ります。
向いている用途と、向かない用途
「この記事を読み終えた」「この設定を選んだ」といった、その人の端末だけで完結する情報に向いています。
逆に、別の端末でも引き継ぎたい情報や、消えては困る情報には使えません。ブラウザを変えれば消えますし、プライベートモードでは残りません。
実装上の注意
サーバー側には存在しない仕組みなので、サーバーで実行される部分から触るとエラーになります。また、環境によっては読み書き自体が失敗するため、失敗しても画面が壊れない書き方が必要です。