技術深掘り・ワークフロー
技術深掘り:リファクタ(モダナイズ)の仕組み
既存コードの中の古い書き方を、決まった手順で見つけ、確かめ、書き換える。1.0で入った「モダナイズ」の流れの公式ドキュメントです。
なぜ要るのか
Web開発の多くは新規ではなく、年月の積み重なった既存コードの上で起きます。古いコードは壊れません。動くので不具合にもならず、動いているものを書き換えるには信頼が要るため、誰も触りません。ただ放置すると、バンドルサイズ、応答性、アクセシビリティの面で静かに損をします。さらに、そのプロジェクトでエージェントを使うと、周囲の2015年頃の流儀と、学習データの古い書き方の両方を真似します。
仕組み
- 決定論的なローカル走査。HTML、CSS、JavaScript/TypeScript、フレームワークの部品、
package.jsonを、AST、DOM、CSSのパーサでローカルに走査します。LLMの呼び出しもトークン消費もありません。 - 規則のカタログは、厳しくふるいにかけられています。候補の規則は約45,000件のオープンソースのリポジトリで試されました。半分で規則を作って調整し、残りの見ていない半分で採点します。既定で有効になるには、静的な一致の精度80%以上、確認後の精度90%以上が必要です。落とした候補のほうが多く、対応する古い書き方がない機能や、実利のない書き換え(動いている兄弟セレクタを
:has()に替える等)は外されています。 - 文脈での誤検出の除去。各規則には
keepWhen/dropWhenの判断基準が付いています。エージェントは周囲のコードを見て、意図的なフォールバックや@supportsのガード、似ているだけのものを捨ててから報告します。 - 対象は高確信度の範囲に絞られています。
legacy-scanが見るのは、約200ガイドのうち決定論的に見つけられる約20%です。残りは、作る作業の中で検索と取得で使われます。範囲は広げていく予定とされています。
呼び方
# 入れる(1.0以上が必要)
npx modern-web-guidance@latest install
# 更新
npx modern-web-guidance@latest update
モダナイズはスキルの中核の定義に含まれるため、エージェントに自然な言葉で「legacy patterns を探して」「modernize して」と頼んでも起動します。ただし、部品を1つ名指しすると通常のガイド検索になります。リポジトリ全体を対象にする頼み方の例です。
Modernize this repository using Modern Web Guidance. Scan our frontend files for legacy patterns, verify the findings, and propose a modernization plan before making any code edits.
Check src/components/forms for legacy web patterns that can be refactored to modern Baseline features.
ターミナルで legacy-scan を直接実行もできます。CI/CDへの組み込みは開発中とされています。
見つける書き方の例
| 分野 | 古い書き方 | 現代的な置き換え |
|---|---|---|
| フォーム | scrollHeight を読むテキストエリアの自動リサイズ | CSS field-sizing: content |
| フォーム | IMEのガードがないEnterの送信処理 | if (e.isComposing || e.keyCode === 229) return; |
| フォーム | 未操作の欄に付く :invalid のスタイル | :user-invalid/:user-valid |
| フォーム | 認証・決済フォームの autocomplete の欠落 | 標準の autocomplete の値 |
| ダイアログ | ドラッグ選択を壊す e.target === dialog のクリック判定 | <dialog closedby="any">+段階的な強化 |
| ダイアログ | オーバーレイの開閉をイベントリスナーで命令的に処理 | popover と popovertarget の宣言的な属性 |
| CSS | max-height: 9999px のアコーディオンのアニメーション | interpolate-size: allow-keywords と calc-size() |
| CSS | 子の状態で親のクラスを切り替えるJavaScript | :has(:checked) などの関係セレクタ |
| CSS | 重複した prefers-color-scheme: dark のブロック | light-dark() 関数 |
| セキュリティ | 完全性ハッシュのないCDNのスクリプトタグ | integrity と crossorigin="anonymous" |
作例1:テキストエリアの自動リサイズ
入力のたびに scrollHeight を読むとレイアウトの再計算が走り、INPを悪くします。今はCSSだけでできます。下の欄は実際に field-sizing: content で伸びます。改行しながら長く打ってみてください。
/* 旧:入力のたびにレイアウトを測る
textarea.addEventListener('input', () => {
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + 'px';
}); */
/* 新:宣言的な field-sizing */
textarea {
field-sizing: content;
min-block-size: 3lh;
max-block-size: 15lh;
}
作例2:宣言的なポップオーバー
クリックのリスナーを書かずに、属性だけで開閉できます。下のボタンが実際の動作です。
<!-- 旧:showPopover() を呼ぶリスナーだけのJavaScript -->
<!-- 新:JavaScriptなし -->
<button popovertarget="menu">Open Menu</button>
<div id="menu" popover>Menu Content</div>
作例3:IMEに安全なEnter送信
日本語、中国語、韓国語の入力中にEnterで変換を確定すると、送信まで走ってしまう事故の対策です。ドキュメントの例では、ガードは送信処理の前ではなく、確定を妨げない位置に入れます。元の例は次です。
textarea.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
if (e.isComposing || e.keyCode === 229) return;
sendMessage();
}
});
進め方は4段階で、自動修正フラグはない
- 走査。
npx modern-web-guidance legacy-scan <path> --jsonが候補のファイルだけにパーサを回します。この時点で誤検出でない確率は約92%で、各一致には確認のチェックリストが付きます。 - 文脈での確認。
scrollHeightの読みが仮想スクロールの一部だったり、@supportsで守られていたりすれば、その指摘は静かに落とされます。 - 報告。確認を通った指摘と、頼まれていればモダナイズの計画をまとめます。
- ガイド取得、書き換え、再確認。
retrieve <guide-id>でガイドを取り、Baselineの互換の書き方で書き換え、直したファイルに再度legacy-scanとテストを回して解消を確認します。
--fix のような自動修正がないのは意図的です。一見単純なモダナイズでも、命令的なリスナーやnpmパッケージを消して振る舞いをHTMLとCSSへ移すような、層をまたぐ書き換えになることが多く、ブラウザ対応の確認も要るためです。原文を読む:How Modern Web Guidance modernizes your codebase—and why you should do it(modernization workflow)
短縮URL(投稿の記載):https://goo.gle/3WHWlNn / 解決先:https://developer.chrome.com/docs/modern-web-guidance/modernization-workflow