【テクニカル・上級編】preタグとcodeタグの組み合わせによるコード表示 – HTML実践ガイド

なぜ、あなたのコードブロックは「ただのテキスト」なのか?:セマンティクスとパフォーマンスの深淵

フロントエンドの現場において、コード表示は単なる「文字列の羅列」ではありません。しかし、多くのエンジニアが `

` をなんとなくの慣習で使い、そこにシンタックスハイライトライブラリを雑に流し込んで満足しています。

もしあなたが、読み込み時にレイアウトシフト(CLS)が発生したり、巨大なソースコードをレンダリングした際にブラウザが数ミリ秒フリーズすることに不満を感じているなら、この記事はあなたのためのものです。

1. セマンティクスの真髄:なぜ pre と code の二段構えが必要か

HTMLの仕様において、`
` は「書式済みテキスト(Preformatted text)」を表す要素です。一方、`` は「コンピュータコードの断片」を示します。

これらを組み合わせる際、単に「見た目を整えるため」と考えるのは三流です。`
` が改行や空白の維持というレイアウトの制約を担い、`` がその中身がプログラム言語であるという文脈をブラウザとスクリーンリーダーに伝達します。



...

// 型安全を意識した関数の定義
const fetchData = async (endpoint: string): Promise> => {
  const response = await fetch(endpoint);
  return response.json();
};

2. レンダリング負荷を極限まで削ぎ落とす:ハイライトの非同期戦略

シンタックスハイライト(Prism.jsやShikiなど)をメインスレッドで実行するのは、特に長大なコードブロックにおいて「ユーザー体験の死」を意味します。トークナイズ処理は意外とCPUを食うからです。

避けるべきアンチパターン

DOMが構築された瞬間に、クライアントサイドでハイライトライブラリを走らせる手法です。これは確実にリフローを引き起こし、JavaScriptの実行時間が長いほどメインスレッドをブロックします。

推奨されるアーキテクチャ:Web Workers + 仮想化

1. ビルド時ハイライト: 可能であればShikiのようなライブラリを使い、ビルド時にHTMLを生成してください。これが最強のパフォーマンスです。
2. Web Workersの活用: 動的にコードを生成・更新する場合、メインスレッドからトークナイズ処理を切り離します。
3. Intersection Observer: ビューポートの外にあるコードブロックは、そもそもハイライト処理を遅延させましょう。

3. TypeScriptによる型安全なラッパーコンポーネント

ReactやVueを使用している場合、単にタグを書くのではなく、型安全なコンポーネントでラップし、エッジケース(特殊文字のサニタイズ漏れなど)を封殺すべきです。

import React, { useMemo } from 'react';

interface CodeBlockProps {
code: string;
language: 'typescript' | 'javascript' | 'css';
}

/

  • 厳格な型定義とエスケープ処理を保証するラッパーコンポーネント

/
export const CodeBlock: React.FC = ({ code, language }) => {
// メモ化により、親コンポーネントの再レンダリング時の不要なハイライト再計算を防ぐ
const highlighted = useMemo(() => {
// ここでハイライト処理を実行(あるいはサニタイズ処理)
return escapeHtml(code);
}, [code]);

return (

      
    

);
};

// クロスサイトスクリプティング(XSS)を回避するための最低限のサニタイズ
const escapeHtml = (unsafe: string): string => {
return unsafe
.replace(/&/g, "&")
.replace(//g, ">");
};

4. 現場で直面する「エッジケース」という名の悪魔

  • タブ文字の扱い: `tab-size` CSSプロパティを適切に設定していますか? ブラウザのデフォルト(通常8スペース)は長すぎてコードのインデントを崩壊させます。`pre { tab-size: 2; }` は必須です。
  • 水平スクロールの罠: モバイルデバイスにおいて、長いコード行がコンテナを突き破ることはよくあります。`overflow-x: auto;` を設定しつつ、`white-space: pre;` を維持するバランスを設計してください。
  • 非同期の競合(Race Condition): 高速にコードを切り替えるUIの場合、前のハイライト処理が完了する前に新しいコードが流し込まれることがあります。`AbortController` を使用して、古い処理を確実にキャンセルする仕組みが、堅牢なアプリには不可欠です。

最後に:美しさは細部に宿る

コードブロック一つとっても、パフォーマンス、セマンティクス、型安全性を突き詰めれば、そこにはエンジニアの矜持が表れます。「動けばいい」という考えから脱却し、ブラウザエンジンがどのようにDOMを解釈し、どのようにメモリを消費するかを想像しながらマークアップを行う。

その小さな積み重ねこそが、洗練されたWebアプリケーションを構築する唯一の道だと私は信じています。さあ、あなたのコードブロックを、次世代のスタンダードへ引き上げてください。

コメント

タイトルとURLをコピーしました