Service Workerを起こさずに通信を振り分ける仕組みがSafariにも届いた

つくば市のホームページ制作会社

web.devが10月2日に公開した9月分のウェブプラットフォーム新機能まとめに、地味ながら気になる項目がありました。Safari 27が、Service Workerの「Static Routing API」に対応したという話です。Chromeでは版123から使えていた機能で、これでSafariとChrome系の両方で動くようになりました。表示速度に関わる仕組みなので、少し掘り下げて紹介します。

Service Workerが抱えていた待ち時間

Service Workerは、ページとネットワークの間に入って通信を仲介するスクリプトです。オフライン表示やキャッシュの制御に使われ、WordPressでもPWA化やキャッシュ系のプラグインを通じて、知らないうちに組み込まれているサイトがあります。

ただ、Service Workerを置くと、そのサイトへのリクエストはいったんService Workerのfetchイベントを通るのが基本です。Service Workerが止まっている状態なら、まず起動させてから処理を始めることになります。結果として、キャッシュから返すだけ、あるいはそのままネットワークへ流すだけのリクエストでも、Service Workerの起動を待つ時間が生じていました。

Chrome for Developersの解説によると、Static Routing APIはこの部分を解消するためのものです。どのパスをどこから取得するかをあらかじめ宣言しておくことで、ブラウザはキャッシュやネットワークから取るだけのためにService Workerを動かさずに済むとされています。web.devの記事でも、起動を待たずに取得できることでページ遷移の速度が上がると説明されています。

インストール時に道筋を登録しておく

使い方は、Service Workerのinstallイベントの中で event.addRoutes() を呼び、振り分けのルールを渡すだけです。ルールは「条件」と「取得元」の組み合わせで書きます。

条件には、URLの形(urlPattern)、リクエストのメソッド、モード、取得先の種類、Service Workerが起動中かどうか、を指定できます。複数の条件を書いた場合は、すべてを満たしたときだけそのルールが使われます。取得元は、ネットワーク、キャッシュ、従来どおりのfetchイベント、ネットワークとfetchイベントを競わせる方式、の中から選びます。名前を指定して特定のキャッシュストレージを使うこともできます。

たとえば、フォームへのPOST送信はService Workerを通さず、そのままネットワークへ送る、という指定は次のように書けます。

addEventListener('install', (event) => {
  event.addRoutes({
    condition: {
      urlPattern: "/form/*",
      requestMethod: "post"
    },
    source: "network"
  });
});

画像の拡張子を条件にして特定のキャッシュから返す、記事ページはService Workerが起動中のときだけfetchイベントに回す、といった書き分けも解説の例に挙がっています。なお、試験提供の段階では registerRouter() という一度しか呼べないメソッドでしたが、利用者の意見を受けて今の addRoutes() に変わったそうです。Chromeの開発者ツールでは、Applicationパネルに登録済みのルールが表示され、Networkパネルでもルールに一致したリクエストを見分けられます。

制作現場で押さえておきたいこと

web.devの対応表を見ると、ChromeとEdgeは版123から、Safariは今回の27から対応していますが、Firefoxはまだ未対応です。対応していないブラウザでは従来どおりfetchイベントで処理されるだけなので、ルールを追加しても表示が壊れるわけではありません。速くなる環境が増えた、と受け止めるのが妥当なところです。

中小企業のサイトで直接この記述を書く場面はそう多くないかもしれません。それでも、Service Workerを使っているサイトを引き継いだときや、キャッシュ系のプラグインを選ぶときに、こうした振り分けに対応しているかどうかは一つの見どころになります。特にお問い合わせフォームや管理画面への通信のように、キャッシュを挟む意味がないリクエストを素通しにできるのは、速度だけでなく不具合の切り分けの面でも助かります。

Service Workerは入れると速くなる一方で、仲介が増えるぶんの負担もある、という両面を持つ仕組みでした。その負担を宣言ひとつで減らせる手段が主要なブラウザにそろってきたので、手元のサイトでService Workerが何を受け持っているのか、一度確かめてみる良い機会だと思います。

ChromeのベータでJPEG XL画像が表示できるようになった

つくば市のホームページ制作会社

Chrome for Developersのブログで、9月16日にベータ版となったChrome 155の変更点がまとめられました。CSSの新しい指定やJavaScriptのモジュール読み込みの改善など項目は多いのですが、画像を扱う制作者として目が留まったのは、JPEG XL(image/jxl)の画像を読み込んで表示する機能がBlink(Chromeの描画エンジン)に加わったことです。

JPEG XLは国際規格ISO/IEC 18181として標準化された画像形式です。紹介記事によると、読み込みの途中から段階的に絵を見せられるプログレッシブ表示に対応しており、体感の表示速度を上げやすいとされています。加えて、広い色域やHDR、高いビット深度、アニメーションも扱えます。写真を多く載せるサイトや、色の再現にこだわる商品写真などとは相性のよい特徴がそろっています。回線の細い環境で大きな写真を見せるとき、最後まで読み込まれるまで空白が続くのか、粗い絵が先に出て徐々に鮮明になるのかでは、見ている人の印象がかなり違います。

中身の実装にも注目したい

今回の対応では、デコード(画像データを表示できる形に戻す処理)に、Rustで書かれたjxl-rsというデコーダーが使われています。記事ではこれを「メモリ安全な純Rust製のデコーダー」と説明しています。画像の読み込み処理は外から届いたデータをそのまま解析する部分なので、昔から脆弱性の温床になりやすい場所でした。新しい形式を受け入れるにあたって、安全性を意識した実装を選んだという点は、ブラウザ側の姿勢として心強く感じます。

とはいえ、今の段階はあくまでベータ版での対応です。正式版にいつ届くか、ほかのブラウザでどこまで使えるかは、それぞれの状況を確かめる必要があります。すぐにサイトの画像をJPEG XLへ置き換えるというより、<picture>要素で対応ブラウザにだけJPEG XLを渡し、それ以外にはWebPやJPEGを返す、という段階的な使い方が現実的でしょう。この書き方なら、対応していないブラウザで画像が欠けることもありません。

ちなみに同じベータ版には、ほかにも制作者に関係する変更が並んでいます。コンテナの先頭や末尾の子要素の余白を切り落とせるCSSのmargin-trimや、読み込みに失敗したJavaScriptのモジュールをあらためて読み込み直せるようにする変更などです。画像の話と合わせて、不安定な回線でも崩れにくいページを作るための部品が少しずつそろってきている印象です。

中小企業のサイトでは、画像の書き出し形式を一度決めたら何年も見直さないことが珍しくありません。WordPressのメディアライブラリや画像最適化プラグインがこの形式をどう扱うかも、今後の動きを見ていきたいところです。私たちも、写真の多い案件から少しずつ試しながら、表示の速さと画質のバランスを確かめていくつもりです。

再読み込みのない画面切り替えも速度計測の対象に

つくば市のホームページ制作会社

表示速度の指標として広く使われている Core Web Vitals には、長いあいだ埋まらない空白があった。JavaScript で画面の中身だけを差し替えるタイプのサイトでは、アドレスバーの URL が変わっても「新しいページを読み込んだ」とは扱われず、最初の読み込み時に測った数値がそのまま残り続けていた。その空白を埋める仕組みが Chrome に入り、解析サービス側の対応もこの夏から動き出している。

操作とURLと描画がそろった瞬間を区切りとみなす

Chrome の開発者向け資料では、この仕組みは「ソフトナビゲーション」と呼ばれている。何をもって画面の切り替わりとみなすかについて、ユーザーの操作が起点になっていること、ユーザーから見える形で URL が変わること、その操作の結果として実際に描画が起きること、という三つの条件が示された。この三つがそろったときにはじめて、ブラウザは新しい時間の起点を置く。

これが長らく難しかった理由も、あわせて説明されている。web.dev の解説によると、画面の一部だけを差し替える作りには標準的な型がなく、URL を更新するタイミングも、中身を読み込む順序も、サイトごとにばらばらだという。ちょっとした表示状態の変化でも URL を書き換えるサイトがある一方、まとまった単位でしか書き換えないサイトもある。この差を無視して一律に数え始めると、かえって実態から離れた数字になってしまう。だからこそ、フレームワークの違いに左右されない共通の線引きが必要だった。

二種類の記録が時系列に追加された

実装は Chrome 151 に入り、既定で有効になっている。パフォーマンスの時系列に、soft-navigation と interaction-contentful-paint という二種類の記録が追加された。前者は操作をきっかけにした同一文書内の履歴変化を報告し、そこから先の計測を最初の URL ではなく現在の画面に結びつける。後者は、操作によって書き換えられた部分に新しく描かれた内容を報告するもので、非同期の読み込みをまたいだ待ち時間も追える。

この二つがあると、切り替え後の画面についても LCP や INP、CLS を区切って測れるようになる。ただし細かい扱いには注意点が多い。同じ画像を出し続けている箇所は再描画されないため LCP の対象から外れ、通常の読み込みと切り替え後とで最大要素が変わることがある。最初のバイトが返るまでの時間にあたる TTFB は、切り替え時には便宜的にゼロとして扱うのが現在の推奨だ。こうした処理を自前で書かずに済むよう、公式の計測ライブラリ web-vitals は v6.0.0 でこの仕組みに対応している。

解析サービス側の数字が動くことがある

ブラウザが対応しても、実際に数値を見るのは解析サービスの画面だ。そちらの動きも出てきている。Cloudflare は 8 月 21 日に Web Analytics の計測改善を告知し、その変更履歴では 9 月 4 日に展開が完了したとしている。従来の全画面遷移に加えて、新しい API が使える環境での切り替えと、使えない環境で履歴の書き換えから推測した切り替えを、それぞれ別の種類として記録するようになった。後者では LCP は取れないが、ほかの指標は取得できるという。

注意したいのは、告知のなかで、ページビューや訪問の集計値、そして LCP の数値が変動しうると明記されている点だ。サイトの作りによって振れ幅は変わる。数字が動いたときにサイト側の不調を疑う前に、計測方法が変わったのではないかと一度立ち止まれるかどうかで、無駄な調査時間はかなり変わってくる。

手元のサイトで気にしておきたいこと

中小企業のサイトの多くは、ページごとに読み込み直す普通の作りなので、この話が直接効いてくる場面は限られる。とはいえ、商品の絞り込み、予約や見積もりの入力画面、地図や一覧の切り替えなど、部分的に画面を差し替えている箇所は珍しくない。そこがどれくらい待たされているかは、これまで数字として残りにくかった部分だ。

現時点で対応しているのは Chromium 系のブラウザだけで、検索まわりで参照される実測データにいつ反映されるかも、まだ示されていない。順位のために慌てて何かを変える話ではない。それでも、開発者ツールの計測画面ではすでに切り替えの区切りが見えるようになっている。自社サイトで JavaScript による画面の差し替えを使っているなら、その部分の待ち時間を一度自分の目で確かめておくと、次に改善に手をつけるときの判断材料になる。

端末の性能の目安をブラウザから受け取る仕組み

つくば市のホームページ制作会社

自分の作業機では軽快に動くのに、お客様の手元ではもたつく。制作の現場では何度も出会う話です。8月25日に安定版が公開されたChrome 152に、この端末ごとの差を扱うための小さな仕組みが入りました。CPU Performance APIと呼ばれるもので、閲覧している端末の処理性能の目安を、ごく粗い段階の数値としてJavaScriptから読み取れます。

使い方はそっけないほど簡単で、navigator.cpuPerformance を参照すると小さな整数が返ってきます。値が大きいほど性能の高い端末、という意味づけです。Chromeの開発者向けブログでは、描画の作り込みを加減する、重い計算を減らす、裏で走らせる処理の量を調整するといった使い方が挙げられています。

これまでは自前で測るしかなかった

仕様草案によると、端末の性能に応じて中身を出し分けたいという要望は以前からあり、実現しているアプリは自前でベンチマーク相当の処理を走らせるか、ウェブには開かれていない内部的な機能に頼っていたとされています。性能を測るために端末に余計な仕事をさせるのは、順序が逆さまな感じもします。提案の目的のひとつは、この無駄をなくすことだと書かれています。

考え方としては、以前からある端末メモリ量の取得と似ています。細かい実測値ではなく、あらかじめ用意された区分のどれに当てはまるかだけを返す。navigator に読み取り専用の値をひとつ足すという形も同じ流儀です。

段階の分け方と、身元の割り出しへの配慮

返る値は1から4までの4段階で、判定できなかった場合は0です。基本の分け方は、OSが報告するコア数をもとにした素朴なもので、1コアなら1、2から4コアなら2、5から10コアなら3、それ以上なら4と決まっています。そのうえで、特定のCPUがコア数から想像される性能と大きく違うと分かっている場合に限り、ブラウザ側が段階を上下に1つずらしてよいことになっています。

おもしろいのは、この区分を将来にわたって動かさないと決めている点です。もっと高性能な端末が出てきたら、既存の端末を格下げするのではなく5段目を足す。同じ端末なら、混雑していても電池が減っていても、いつでも同じ値を返す。古い端末で古いアプリを開いたときの見え方が、時間が経っても変わらないようにするための約束事です。

もうひとつの軸が、閲覧者の身元を割り出されにくくすることです。CPUの製造元や型番、コア数をそのまま渡せば、端末を特定する手がかりが増えてしまいます。そのため仕様では、それぞれの段階に既存のCPU機種の1割以上、実際に使われている端末の1割以上が入るくらいの粗さを保つべきだとしています。利用できるのはHTTPS接続の場面に限られます。

参考値として付き合う

気に留めておきたいのは、この値が絶対的な事実ではないことです。Chromeでは閲覧者自身が設定画面から報告される段階を上書きでき、組織のパソコンでは管理者が方針で指定することもできます。値はあくまで判断の材料であって、これを根拠に機能を完全に閉ざす作りにすると、上書きした人が困ることになります。

他のブラウザの姿勢も、現時点では表明されていません。提案文書でChromeは前向きとされている一方、Edge、Firefox、Safariは公開の意見なしと記されています。当面はChromeだけで読める値だと考え、取得できないときや0が返ったときにどう振る舞うかを先に決めておく必要があります。仕様の例では、判定できなかった端末は高性能側と同じ扱いにしています。

加えて、この値が示すのは端末の地力であって、いまその端末が忙しいかどうかではありません。今この瞬間の混み具合を見たい場合は、別途用意されているCompute Pressure APIと組み合わせる想定です。読み込み時に演出を出すかどうかを決め、その後の負荷を見ながら止めたり戻したりする、という二段構えの例が示されています。

中小企業のサイトで、この値をすぐに使う場面はそう多くないはずです。ただ、同じページでも端末によって体験がまるで違うという前提は、値を読むかどうかとは関係なく効いてきます。凝った動きを見せ場にするなら、それが動かない端末でも内容が伝わるか。制作側が握っているのは結局そこで、こうしたAPIはその判断を少しだけ具体的にしてくれる道具だと考えています。

部品ごとの表示時刻をブラウザに数えてもらう

つくば市のホームページ制作会社

サイトの速さの話をするとき、話題はどうしてもページ全体の評価に寄っていきます。表示速度の指標が良いか悪いか、という会話は、1枚のページを丸ごと1つの数字にまとめた見方です。ただ、実際に手を動かしていて困るのは、もっと部分的なところではないでしょうか。商品の価格や在庫の表示だけが後から差し替わる、同意バナーが本文より遅れて覆いかぶさる、問い合わせフォームの中身だけがしばらく空白のまま残る。ページ全体としては速いのに、利用者が待っているその一角だけが遅い、という状況です。

この「部品ごとにいつ見えたのか」をブラウザ側で数えてもらう仕組みが、試験提供の段階に入りました。Container Timingと呼ばれるもので、Bloombergが提案し、Igaliaの手でChromiumに実装されたものです。Chromeの開発者向けブログでは、Chrome 148からオリジントライアル、つまり本番のサイトで期間限定で試せる段階に入ったことが案内されています。

ページ全体の指標では届かない場所

いま広く使われている表示速度の指標は、いずれもページを単位にしています。最初に何かが描画された時点、いちばん大きな内容が描画された時点。どちらも利用者の体感を大づかみに表すには便利ですが、面積が大きいことと、その部品が大事であることは別の話です。

商品ページを思い浮かべると、写真、価格と在庫、レビュー、おすすめ商品、決済のウィジェット、同意バナー、外部のチャットといった部品が同居しています。サーバー側で組み立てられるものもあれば、読み込み後にブラウザ側で描かれるもの、外部との通信を待ってから出てくるものもあります。この中で最大の面積を占めるのはたいてい写真ですが、購入の判断を止めているのは価格や在庫の表示だったりします。

さらに、いちばん大きな内容の描画時間は、利用者が操作した時点で計測が打ち切られます。気にしている部品がスクロールやクリックのあとに現れるなら、その部品は指標に載らないまま終わります。実際の訪問者から集めた計測データを扱っている事業者の記事では、同じページ、同じ機種でもこの数値は訪問者ごとに揺れる、と説明されています。画面の広さの違いもありますが、操作で計測が止まることも理由の1つです。

囲んで名前をつけるだけの計測

Container Timingのやることは、拍子抜けするほど単純です。測りたいひとかたまりの外側の要素に containertiming という属性を書き、値として自分でつけた名前を入れる。それだけです。

あとは PerformanceObserver で container という種類の記録を購読すると、その内側に内容が描かれるたびに通知が届きます。届く記録には、自分でつけた名前、最初に描画された時刻、最新の描画の時刻、これまでに描かれた面積の合計、最後に描画のきっかけになった要素などが入っています。描画がコンポジタに渡された時刻と、画面に出た時刻を分けて受け取ることもできます。

逆に、数に入れたくない部分には containertiming-ignore という属性を書きます。同意バナーの中のボタン、読み込み中の骨組み表示、装飾目的の要素、計測のために差し込んだ表示など、数えると面積が水増しされてしまうものを外せます。囲みの中に大きな別部品がある場合、これを外しておくとDOMをたどる処理も軽くなる、という副次的な効きもあるようです。

要素単位の計測と何が違うのか

これまでも elementtiming という属性で、個々の要素の描画時刻を測ることはできました。ただ、これは1つの要素につき1回きりの合図です。ウィジェット全体がいつ揃ったのかを知りたければ、中身の要素すべてに印をつけて回る必要があり、しかも後から差し込まれる要素には印がついていません。自社で書いていない部品には、そもそも手を入れられません。

提案の説明文書では、この不足を埋めるために書かれたJavaScriptの補助実装が引き合いに出されています。描画が始まる前にすべての子要素へ印をつけ、DOMの変化を監視して新しく入ってきた要素にも印をつけ、描かれた矩形を自前で管理する。動きはするものの、そのために描画をせき止めることになり、計測したい速さを計測が損なうという本末転倒に近い形になっていました。この補助実装は現在保守を終えており、正確な値が必要ならブラウザ側の実装を使うよう案内されています。

もう1つの違いは、記録が一度で終わらないことです。ひとかたまりの中身は、文字が先に出て、画像が後から届き、遅れて読み込まれるアイコンがさらに後から乗る、という順に埋まっていきます。そのため記録は候補として複数回届き、どの時点をその部品の揃った時刻と見なすかは書き手が決めます。面積の増加が止まったところを採る、最初の1件だけを採る、利用者の操作が起きるまでを採る。そうした選び方が想定されています。

ブラウザの内側でどう数えているか

実装を担当したIgaliaの技術記事では、既存の仕組みを組み替えて作った経緯が説明されています。Blinkの描画処理には、いちばん大きな内容の描画時間や要素単位の計測のために、文字と画像の描画を検出する部分がすでにあります。新しく描画の追跡を作るのではなく、そこで拾った情報を集約する道を足した、という説明です。

DOMが組み立てられる段階で、containertiming が書かれた要素とその子孫には内部的な目印が立てられます。containertiming-ignore があれば、そこで目印の伝播が止まります。おかげで描画が起きたときに、それが計測対象かどうかを即座に判断でき、対象でない場合の負担はほとんど生じません。対象だった場合は、描かれた要素からDOMを上にたどり、印のついた祖先へ報告が上がっていきます。

面積の集計には、描かれた矩形を重複なく足し合わせる領域計算が使われています。Skiaの領域オブジェクトを流用して、新しい描画のたびに既存の領域との和を取る形です。面積が増えない描画は記録として送られないので、通知の数も抑えられます。計測そのものが重くなっては意味がない、という割り切りが、この辺りの設計に表れているように見えます。

現時点の制約もはっきり書かれています。追跡できるのは文字と画像の描画で、動画やcanvas、SVGはまだ対象外です。Shadow DOMの扱いも初版では見送られており、要素単位の計測での方針が固まってからの検討とされています。深い階層を上にたどる処理の重さも、今後の最適化課題として挙げられています。

どこに印をつけると意味があるか

あらゆる部品に印をつけて回るのは、おそらく得策ではありません。実際の訪問者から計測データを集めている事業者の記事では、利用者の目に入り、かつ商売として意味のある部分から始めるのがよい、という考え方が示されています。売上や離脱に効く場所、先に進めなくなる場所、遅いと苦情の原因になる場所です。

具体例として挙がっているのは、冒頭の主役となる領域、商品のバリエーション選択、購入内容の確認、検索結果の一覧、同意バナー、外部から読み込まれるウィジェットあたりです。とくに同意バナーは、外部の仕組みがブラウザ側で組み立てることが多く、画像も見出しも持たない作りだと要素単位の計測では捉えにくいという事情があります。画面を覆って操作を止めるものなのに、既存の指標には載りにくいわけです。

地方の中小企業のサイトに置き換えるなら、規模は小さくても構図は同じです。トップの主役画像、料金表、予約や問い合わせのフォーム、地図の埋め込み、外部のカレンダー。このうちどれかが遅れて出てくることに心当たりがあるなら、名前をつけて測ってみる価値があります。名前は人間が読んで分かるもので、かつ商品IDのように変動する値は避けるべきだ、とも助言されています。集計したときに散らばってしまうからです。

注意したい点もいくつかあります。印は描画より前に存在していなければならず、後からJavaScriptで属性を足すと、それまでの描画は取りこぼされます。画面の外にある部分は記録されず、後からスクロールして見えても新しい記録が出るとは限らないので、表示領域に入ったかどうかを知る仕組みの代わりにはなりません。読み込み中の骨組み表示を囲みの中に入れたままにすると、その骨組みも描画として数えられます。最終的な中身の側に印をつけ直すか、骨組みを除外するか、集め方を調整するかの判断が要ります。

試験提供という段階の受け止め方

オリジントライアルはChrome 148から始まり、153までの期間が示されています。手元で試すだけなら実験的なウェブプラットフォーム機能の設定を有効にすれば足りますが、実際の訪問者から値を集めたい場合は、サイトごとに発行されるトークンをページに埋め込む必要があります。

このトークンの置き方には、先行して試した事業者がつまずいた落とし穴が紹介されています。ふつうは、機能を使うJavaScriptより前にトークンが読まれていれば動きます。ところがContainer Timingでは、属性そのものも試験提供の対象です。つまりブラウザが最初の containertiming 属性に出くわす前にトークンが読まれている必要があり、計測用スクリプトを描画の妨げにならない形で読み込んでいると間に合いません。結局、サイト側で自分のトークンを登録してもらって初めて値が集まり始めた、という顛末が書かれています。

集めた数値の読み方にも工夫が要ります。ある部品の描画時刻をそのまま見ると、ページ全体の遅れを丸ごとかぶった値になります。たとえば表示の切り替えのために本文全体を数秒隠す仕掛けが入っていれば、その裏で待たされた部品の時刻もそろって遅くなる。それをその部品のせいだと読むのは無理があります。そのため、最初に何かが描画された時刻を引いて差分で見る、という扱い方が採られています。ページが出始めてから、その部品が出るまでに何秒余計にかかったのか。こちらのほうが、直す場所を決めるには役に立ちます。

仕様はまだ動く可能性があり、項目名や細かい挙動が変わることも十分あります。集めた値も、当面は長く追いかける指標ではなく、早い段階の観測データとして扱うのが無難でしょう。それでもこの手の話は、標準になってから慌てて追いかけるより、試験提供のうちに1つか2つ印をつけて眺めておくほうが、広く使えるようになったときの動きが速くなります。属性を書き足すだけで始められるのは、入り口としてはかなり低いほうだと思います。

ライブラリの棚卸しにBaselineを使うという発想

つくば市のホームページ制作会社

一度入れた外部ライブラリを、あとから見直すことはあまりない。動いているし、テストも通っているし、あえて触る理由がない。ただ、その間にもブラウザ側は動いていて、いま package.json に並んでいるもののうち何割かは、すでにブラウザが自前で持っている機能と重なっている。Smashing Magazine に出た依存関係の棚卸しの記事が、その重なりを具体的な数字で示していて面白かった。

入れたきりの依存が積み上がっていく

記事によると、中規模のJavaScriptアプリでは、圧縮後でおよそ60KBから90KB分の依存が、いまやブラウザ側で代替できる範囲に入っているという。日付や数値の書式、HTTP通信、モーダル、ツールチップ、オブジェクトの複製、配列のグループ化。数年前までは確かに穴だった領域が、順に埋まってきた結果だ。

それでもライブラリが残り続けるのは、怠慢だからではないと筆者は書いている。セキュリティの観点で npm audit は回していても、「このライブラリは今もブラウザにできないことをやっているのか」という問いを立てる機会が、そもそも運用の中に組み込まれていない。だから入れたまま何年も過ぎる。複数サイトの保守を抱えている制作の現場だと、この感覚は身に覚えがあるのではないかと思う。

Baselineという安全度の目盛り

棚卸しの物差しとして使われているのが Baseline だ。WebDX Community Group による指標で、ある機能が主要ブラウザ(Chrome、Edge、Firefox、Safari)でどこまで安全に使えるかを三段階で示す。全エンジンには載っていない「限定的な利用可能性」、出そろった直後の「新しく利用可能」、出そろってから30か月が経った「広く利用可能」という並びになっている。

この30か月の差が、棚卸しでは効いてくる。広く利用可能なものは、基本的に今日そのまま置き換えを検討できる。新しく利用可能な段階のものは、自分のサイトの訪問者層を確かめてから決める話になる。状態は webstatus.dev や、MDN の各機能ページに付いているバッジで引ける。

消す前に通しておきたい三つの問い

「ブラウザができるようになった」と読んで、すぐ削り始めないほうがいい、というのが記事の立場だ。紙の上では無料に見える置き換えが、一部の利用者の環境を静かに壊すことがあるし、気づかずに頼っていた機能を落とすこともある。そこで、削る前に三つ確認する。

ひとつめは、代替となる機能が自分の利用者にとって安全かどうか。一般論としてのBaselineではなく、アクセス解析や browserslist の設定と突き合わせて判断する。社内向けの管理画面と、古い端末からの流入が長く続く一般向けサイトでは、答えが変わる。

ふたつめは、置き換えの費用。ブラウザ側の対応が足りずポリフィルを足すことになり、それが外したライブラリより重ければ、容量は増えている。

みっつめは、ブラウザの機能が実際の使い方をカバーしているか。ライブラリは見た目の似た標準機能より多くの仕事をしていることが多い。記事が挙げているのが axios で、fetch に置き換えると、404や500で拒否されない、共通処理を差し込むインターセプタがない、自動再試行がない、アップロードの進捗が取れない、といった差が出る。実際にどこまで使っているかを見てから決める、という順番になる。

置き換えが効きやすいのは書式と画面部品まわり

記事はライブラリを一個ずつではなく、かたまりで見ていく。いちばん取りやすいのが国際化まわりで、相対時間、数値や通貨の書式、複数形、配列を文章に連結する処理は、ブラウザの Intl 系で大半が置き換えられる。この一群でおよそ14KBという計算だ。ただし継続時間の書式は主要エンジンに出そろったのが2025年3月で、広く利用可能になるのは2027年の見込みとされている。

もうひとつ大きいのが画面部品で、こちらはツールチップやポップオーバーのライブラリまで含めて合計およそ24KB。このうちモーダル用のライブラリ、フォーカスを閉じ込める処理、背景のスクロールを止める処理が、dialog要素とCSSの一行にまとまる。showModal で開けば、フォーカスが中に移り、背後が操作できなくなり、Escapeで閉じ、閉じたあとは元の要素にフォーカスが戻る。重なり順もブラウザが面倒を見るので、z-index と格闘しなくてよくなる。手書きの実装より結果的に読み上げ環境への配慮が行き届く、という指摘もうなずける。

通信まわりも同じ見方ができる。よく使われるHTTPクライアントは圧縮後で17KBから19KBほどあり、単純な取得や送信であれば fetch と中断用の仕組みで足りる。タイムアウトも標準の指定で書ける。ここは前述のみっつめの問いが効く場所で、共通処理や再試行に頼っているなら、外した分を自分で書き直すことになる。

配列やオブジェクトの操作も、グループ化や深い複製、集合の和や積は標準側に入った。一方で debounce と throttle には今も標準の代わりがないので、そこは残す。全部捨てるという話ではなく、ブラウザがすでに持っている部分を二重に配らない、という整理だ。

今は手放さないという判断も同じ枠組みから出る

この記事の良いところは、置き換えない例をきちんと入れているところだ。JavaScriptの日付処理を置き換える Temporal は、2026年3月に仕様策定の最終段階に達し、Firefox と Chrome には載ったが、Safari の安定版にはまだ来ていない。全ブラウザで使うにはポリフィルが要る。

そこで数字を並べると、軽量な日付ライブラリが圧縮後3KB程度なのに対し、公式のポリフィルは44KB前後ある。今すぐ乗り換えると容量は減るどころか増える。三つの問いに通すと、機能の良さでは勝っていても、利用者の範囲と費用で落ちる。だから今は現状維持で、Safari が対応してBaselineに入った時点でもう一度見る。判断を「保留」として記録しておける枠組みは、実務では地味に効く。

ブラウザ側の受け皿は今も増えている

置き換え先が増え続けているのも事実で、Chrome 150では、矢印キーでの移動やフォーカス位置の記憶を属性の指定だけで賄える focusgroup が入った。従来は tabindex を書き換える手書きのスクリプトで実現していた部分だ。文字を枠幅に合わせて拡縮する text-fit や、border-image の回り道なしでグラデーションの枠線を描ける background-clip の新しい値も同じ流れにある。

続く Chrome 151 のベータでは、コンポーネントの内側にある要素を aria-labelledby などから参照できる仕組みや、複合的な部品の中の補助的な操作を支援技術に伝える aria-actions が挙がっている。手書きのJavaScriptで補っていた振る舞いが、少しずつ宣言的な記述に移っていく。

中小企業向けのサイトだと、そもそも巨大な依存を抱えていないことも多い。それでも、テーマやプラグインが読み込んでいるものを一度数えてみる価値はある。四半期に一度、本番に出ている依存だけを並べ、それぞれが実際のビルドでどれだけ容量を占めているかを解析ツールで測り、代わりになる機能のBaselineの状態を確かめる。そのうえで先ほどの三つの問いに通し、いま標準になっているものを返していく。それだけで表示は軽くなり、更新を追いかける対象も減る。まずは一つの分野だけ選んで手元の設定ファイルを開いてみる、という始め方が現実的だと思う。

アップロードした画像の変換がブラウザ側で行われるようになる

つくば市のホームページ制作会社

WordPressで写真をアップロードしたとき、裏側では何が起きているか。サーバー上のPHPが元画像を読み込み、縮小版を何種類か書き出し、必要なら形式を変換している。撮ったままの大きな写真を何十枚もまとめて投げ込むと、この処理が重くて途中で止まる。更新担当が自分で写真を載せている中小企業のサイトでは、よくある詰まりどころだ。

今月中旬に公開が予定されているWordPressの次の版では、この画像処理の担当がサーバーからブラウザに移る。開発チームの解説によると、圧縮、リサイズ、形式変換、回転、サムネイル生成までを、操作している人の手元のブラウザで済ませる仕組みだという。

画像処理のエンジンがブラウザの中で動く

使われているのはwasm-vipsと呼ばれるもので、画像処理ライブラリのlibvipsをWebAssemblyに変換し、ブラウザ上で動かせるようにしたものだ。処理はWeb Workerに逃がしてあるため、変換の最中でも編集画面の操作が固まりにくい。

副次的な効果として、書き出される画像そのものも変わる。libvipsが生成するJPEGは、これまで使われてきたGDやImagickによるものよりおよそ15パーセント小さくなるとされている。サーバーに入っている画像ライブラリの違いで書き出し結果が微妙に変わっていたのが、どの環境でも同じ出力に揃う点も見逃せない。共用サーバーを使う案件が多いほど、この均一さはありがたい。サーバーごとの環境差を吸収するために、書き出し品質の設定を案件別に調整していた人には、手間が一つ減る話でもある。

iPhoneの写真やアニメーションGIFの扱いも変わる

分かりやすいのはHEICへの対応だろう。iPhoneの標準的な写真形式だが、これまではサーバー側の対応状況次第でアップロードできないことがあった。新しい仕組みではブラウザ内でデコードしてJPEGに変換し、元のファイルは別途保持される。

AVIFは10ビットや12ビットといった高階調の元データまで通り、UltraHDRのJPEGはゲインマップを保ったまま各サイズが書き出される。透過のないアニメーションGIFはMP4やWebMの動画に変換され、エディタ側では自動再生とループが効く動画ブロックの派生として挿入される。見た目は元のGIFのままで、ファイルだけが軽くなる形だ。

条件を満たさない環境では今までどおりになる

気になるのは、対応していない環境で何が起きるかという点だが、ここは素直な作りになっている。条件を満たさない場合は従来どおりサーバー側で処理され、切り替えは自動で、画面上の見え方も変わらず、エラーも出ない。判定には端末のメモリ量やCPUのコア数、通信速度、CSPでblobが許可されているかどうかが使われる。

ブラウザ側の条件はやや厳しめだ。SharedArrayBufferを使う都合でDocument-Isolation-Policyに対応したChromium系のブラウザが必要で、FirefoxとSafariは当面サーバー側処理に回る。ただしHEICのデコードだけはSafariでも動く。サイト側で機能ごと止めたい場合はwp_client_side_media_processing_enabledフィルターをfalseにすればよく、big_image_size_thresholdやjpeg_qualityといった既存のフィルターもそのまま効くとされている。

制作の現場から見て効いてくるところ

実務でありがたいのは、PHPのメモリ上限に起因するアップロード失敗が減ることだ。画像処理はメモリを食う工程で、共用サーバーの上限に当たって管理画面が真っ白になる相談は今でも珍しくない。その負荷がブラウザ側に移るなら、サーバーの構成を触らずに回避できる場面が増える。手元のパソコンは近年それなりに性能が上がっているので、重い工程を任せる先としては悪くない。

アップロードの粘り強さも上がっている。サイズ違いの書き出しごとにリクエストが分かれ、失敗すれば間隔を空けて自動で再試行する。回線が切れれば一時停止し、つながれば再開する。進捗も画面に出て、読み上げソフトにも伝わる作りだ。出先からスマートフォンで写真を上げる担当者がいるサイトほど、この差は体感しやすいだろう。

正式な公開は今月中旬の予定になっている。普段どおりの写真の投げ方を検証環境でひととおり試し、いつも使っている画像形式が想定どおりに変換されるかを見ておくと、切り替わったあとに慌てずに済む。

読み込み直さない画面切り替えの速さをChromeが測れるようになった

つくば市のホームページ制作会社

サイトの表示速度を測る指標として、Core Web Vitalsはすっかり定着しました。ところが、この指標には長らく穴があると言われてきました。ページを読み込み直さずに中身だけを差し替える作りのサイトでは、最初の一回しか計測されないという問題です。Chromeの最新版で、この部分をブラウザ側で測る仕組みが正式に使えるようになりました。

Chromeの開発者向け資料によると、Soft Navigations APIと呼ばれるこの機能は、試験運用の期間を経て、2026年7月に公開された版から設定を切り替えずに利用できるようになりました。名前のとおり、ソフトナビゲーション、つまり読み込み直さない画面遷移を計測の対象にするものです。

これまで測れていなかった部分

従来のCore Web Vitalsは、ブラウザがURLを開いて新しい文書を読み込む、いわゆる通常の遷移を前提に設計されています。表示までの時間を示すLCP、レイアウトのずれを示すCLS、操作への反応を示すINPは、どれもそのページが開かれた時点を起点に集計されます。

JavaScriptで画面を組み立てる作りのサイトでは、二画面目以降はURLだけが書き換わり、文書の読み込みは起きません。ブラウザから見れば一枚のページがずっと開かれたままなので、二画面目の表示がどれだけ遅くても、最初の一枚の数字に埋もれてしまいます。逆に、最初の表示さえ速ければ全体が良好に見えてしまうこともありました。計測ツール側で独自に区切りを入れる回避策はありましたが、実装ごとに基準が違い、横に並べて比べられる数字にはなりにくい状態でした。

ブラウザはどこで区切りを判断するのか

新しい仕組みでは、ブラウザ自身が三つの条件をもとに画面の切り替わりを見分けます。利用者の操作がきっかけになっていること、利用者から見えるURLの変化を伴うこと、そしてその結果として実際に画面が描き直されること。この三つがそろったときに、ひとつの区切りとして扱われます。

あくまで推測にもとづく判定なので、公式の説明でも、サイトの作り方によっては拾いすぎたり拾いそこねたりすることがあると断っています。それでも、判定の基準がブラウザ側に統一されたこと自体に意味があります。計測ツールを乗り換えても、同じ考え方で区切られた数字が並ぶからです。

計測する側で増えたもの

開発者から見ると、パフォーマンス情報を受け取る仕組みに新しい種類の記録が追加された形になります。切り替わりそのものを表す記録と、切り替わったあとの主要な描画を表す記録が加わり、既存の各種タイミング情報にも何番目の遷移かを示す値が付くようになりました。これで、ひとつの記録がどの画面のものかを判別できます。

ただし、これらを直接扱うのはそれなりに骨が折れます。読み込み直さない遷移では最初の応答までの時間がゼロとして扱われるなど、通常の遷移とは数字の意味が変わる場面もあるためです。Googleが公開している計測用のライブラリweb-vitalsは、新しい版でこのあたりを内部で吸収するようになっており、URLの対応付けや数値のリセットを任せられます。自前で計測基盤を持っているところ以外は、ライブラリの更新に乗るほうが現実的でしょう。

今すぐ効いてくる話ではない

注意しておきたいのは、この計測結果が検索での評価にそのまま反映されるわけではない点です。実利用者のデータを集めたChrome User Experience Reportにも読み込み直さない遷移の分を加えることは目指されていますが、どのような形で反映されるかは未定とされています。対応もChromium系のブラウザに限られます。つまり現時点では、自分たちで測って改善に使うための道具という位置づけになります。

WordPressで作られた一般的な企業サイトのように、リンクを踏むたびにページを読み込み直す作りであれば、直接の影響はほとんどありません。関わってくるのは、予約や検索の絞り込み、会員向けの管理画面など、画面の一部だけを差し替える作りを取り入れている場合です。最近はView Transitionsのように、通常の遷移でもアプリらしい見せ方ができる手段が増えており、境目は少しずつ曖昧になっています。

数字が見えるようになると、これまで感覚で語られていた二画面目が重いという話を、根拠を持って共有できるようになります。制作側と運用側で改善の優先順位を決めるとき、この差は思ったより大きいはずです。

サイト内検索の遷移先を先読みできるChromeの新しい指定

つくば市のホームページ制作会社

ページの表示を速くする手段のひとつに、リンク先を先に読み込んでおく先読み(prerender)がある。ChromeではSpeculation Rules(投機ルール)という仕組みが用意されていて、JSONを数行書くだけで、どのページを先読みするかをブラウザに伝えられる。先読みといっても中身は実際にページを読み込んで表示の準備まで済ませておく処理で、遷移した瞬間に画面が出るのが特徴になる。ただしこれまでは、フォームの送信による画面遷移には効かなかった。7月に安定版へ上がったChrome 151で、その穴が埋まっている。

新しく使えるようになったのは、prerenderのルールに書けるform_submissionというフィールド。サイト内検索のように、送信すると /search?q=… といったGETリクエストの遷移になるフォームを対象に、遷移先をあらかじめ用意しておける。これまでもURLを指定した先読み自体は書けたのだが、実際の遷移がフォーム送信だと用意した先読みを使えず、結局その場で読み込み直しになっていた。ブラウザ側から見れば、使われないページの準備に通信量とCPUを費やしていたことになる。今回の指定は、フォーム送信という遷移の種類そのものを先読み側に伝えるもので、ボタンを押した瞬間に用意済みのページへ切り替えられる。Chromeは146でオリジントライアルとして試したうえで、151からデスクトップとAndroidで正式に有効化した。WebViewは対象外のままとなっている。

サイト内検索を抱えるサイトでの使いどころ

商品検索や記事検索を備えたサイトは、規模を問わず多い。検索結果ページは一覧の組み立てやデータベースへの問い合わせが挟まるぶん、トップページより重くなりやすい。そこを先読みで前倒しできれば、押してから表示までの体感は変わってくる。もっとも、先読みしたのに遷移しなかった分はそのまま無駄になるので、あれもこれもと広げる性質のものではない。先読みは通信環境や省データ設定によってブラウザ側の判断で見送られることもあり、必ず効くものとして設計するより、効いたら速いという上乗せとして扱うほうが無難だと思う。対象を選ぶときは、アクセス解析でよく使われている検索欄はどれかを先に見ておくと判断しやすい。

気をつけたいのはサーバー側の負荷とアクセス解析の扱い。WordPressのサイト内検索は結果がURLごとに散らばるためキャッシュが効きにくく、先読みの指定を広げるとリクエストだけが増えることもある。計測についても、先読みされた時点と実際に表示された時点をどう数えるかはツールによって差がある。また、今回想定されているのは検索フォームのようなGETでの遷移で、POSTで送る問い合わせフォームの類は同じようにはいかない。ChromeのDevToolsには投機ルールの動作を確認する画面があるので、まずはそこで先読みが成立しているかを見ながら、よく使われる検索フォームひとつに絞って試すあたりが現実的なところだろう。

gzipやBrotliに続く圧縮方式zstd、全ブラウザ対応が揃う

つくば市のホームページ制作会社

ウェブページやファイルをブラウザに届けるとき、多くのサーバーは中身を圧縮してから送っている。長年その主役はgzipで、近年はより縮むBrotliが加わってきた。ここに三つ目の選択肢として、zstd(Zstandard)という圧縮方式が本格的に使えるようになりつつある。ChromeやFirefoxはすでに対応済みで、遅れていたSafariも直近のアップデートで足並みをそろえた。主要ブラウザが一通り対応したことで、実務でも検討できる段になってきた。

そもそも転送時の圧縮とは何か

HTMLやCSS、JavaScriptといったテキストは、そのまま送るとサイズが大きい。そこでサーバーは送信前にデータを圧縮し、ブラウザが受け取って展開する。この仕組みが転送時の圧縮で、リクエストのAccept-Encodingヘッダーでブラウザが対応方式を伝え、サーバーがContent-Encodingヘッダーで実際に使った方式を返す。読者から見えないところで、日々のページ表示を支えている土台のような機能だ。

gzipは登場からかなり時間が経っているが、いまも事実上すべての環境で通じる共通語として残っている。Brotliはgzipよりよく縮む方式で、Googleがウェブのために設計した。同じファイルでもより小さくなるため、公開サイトの配信では定番になってきた。zstdはMetaが開発した比較的新しい方式で、IANAの圧縮方式一覧にも「zstd」という名前で正式に登録されている。

zstdはどのあたりに位置するのか

三つの方式は、縮む度合いと処理の速さのバランスが少しずつ違う。ざっくり言えば、圧縮率はBrotliがもっとも高く、gzipが控えめ、zstdはその中間あたりに収まる。一方で圧縮にかかる時間はzstdが速く、条件によってはBrotliの最高設定より数倍速く処理できるとされている。縮み具合と速さのどちらを取るかという、昔からある悩みに新しい落としどころを用意した方式だと言える。実測を比べた記事でも、zstdはgzipより一回り小さく縮めつつ、処理そのものは軽いという傾向が繰り返し報告されている。数字の細部は圧縮の強さの設定やファイルの中身で変わるため、自分のサイトで試してみて初めて分かる部分も多い。

この特性から、zstdはその場で圧縮して送る動的なコンテンツと相性がよい。ページを表示するたびに圧縮し直す場面では、少しでも速く処理できるほうが待ち時間の短縮につながるからだ。逆に、あらかじめ圧縮しておける静的なファイルなら、時間をかけてでも最小サイズを狙えるBrotliの最高設定が向く。一度圧縮すれば以後は使い回せるため、処理速度の差はほとんど問題にならない。用途によって使い分けるのが素直な考え方になる。

導入で押さえておきたい前提

実際に使うにはいくつか条件がある。まず、Chromeはzstdを安全な通信、つまりHTTPS接続のときだけ候補として提示する。暗号化されていない通常のHTTPではgzipやBrotliに戻る。常時HTTPS化が当たり前になった今ならほとんどのサイトが該当するが、頭の片隅には置いておきたい。ブラウザごとの対応状況はCan I useのような一覧で確認できる。

サーバーやCDN側の対応も欠かせない。CDN大手のCloudflareは以前からzstdを扱えるようにしており、配信基盤としての土台は整いつつある。自前のサーバーで有効にする場合は、使っているウェブサーバーソフトがzstdに対応しているかを確認することになる。ブラウザが受け取れても、送り出す側が方式を用意していなければ実際には使われない。両側がそろって初めて効いてくる点は、gzipやBrotliと同じ理屈だ。

中小規模のサイトでどう受け止めるか

では今すぐ全サイトがzstdに乗り換えるべきかというと、そこは冷静でよい。多くの中小企業サイトは、gzipやBrotliがすでに効いていれば体感できる速度は十分に出ている。zstdはあくまで選択肢が一つ増えたという話であり、乗り換えないと遅れるという性質のものではない。既存の圧縮が正しく効いているかをまず確かめるほうが、ずっと実益は大きい。

それでも、配信の速さを突き詰めたい場面や、動的に生成する部分が多いサイトでは、zstdが効いてくる余地がある。地方の制作現場でも、圧縮方式の違いと使い分けの勘どころを知っておけば、サーバーやCDNを選ぶときの判断材料が一つ増える。ブラウザ側の対応が一巡した今は、その知識を仕込んでおくのにちょうどよい頃合いだ。