Produced by FOURIER

JavaScriptの読み込み時にblocking="render"でFOUC対策

SenaSena calender 2023.11.10

はじめに

以前、JavaScript呼び出し時の async にていての記事を書きました。

JavaScriptの呼び出しにasyncを付けない方がよいときってどんなとき? | FOURIER TECH BLOG 〜 IT技術ブログ 〜

Web Componentsが呼び出される際に、Layout Shiftと判定される可能性があることに気づいたので解説します。

https://www.fourier.jp/techblog/articles/call-webcomponents-with-perser-blocking/

要約すると、JavaScriptのコードの内容によっては、defer や async で読み込むと FOUC(ちらつき)が発生してしまうことがあるという内容になります。

Flash of unstyled content(FOUC)について

Flash of unstyled content - Wikipedia

https://en.wikipedia.org/wiki/Flash_of_unstyled_content

特に React や Vue.js を使ったサイトでは、ローディング画面を作って FOUC を防止することが多いと思いますが、閲覧者にとっては(ブラウザの)ローディングした後にローディングとなってしまいます。

なんとかする方法は無いかと Chrome の開発ブログを見ていましたが、ついに出ました!

'blocking=render' attribute on scripts and style sheets - Chrome Platform Status

https://chromestatus.com/feature/5452774595624960

FOUC への救世主 blocking="render"

Feature proposal: blocking=render attribute on <link>, <script> and <style> · Issue #7131 · whatwg/html

https://github.com/whatwg/html/issues/7131

<script async blocking="render" src="async-script.js"></script>

blocking="render"を付けることにより、レンダリングの開始前に評価されます。

今まではレンダリングされた後に評価・実行されてしまっていたので FOUC が発生していましたが、これで防ぐことが出来ます!

軽く実験

以下のような JavaScript を書いたとします。

"use strict";
{
  const root = document.getElementById("root");
  const div = document.createElement("div");
  div.style.paddingBlock = "1000px";
  root.appendChild(div);
}

同じコードを head タグ内から様々な方法で読み込んでみます。

  1. 同期的に読み込みます。
<script src="/js/app.js"></script>
  1. defer で読み込みます。
<script defer src="/js/app.js"></script>
  1. async で読み込みます。
<script async src="/js/app.js"></script>
  1. 2.に blocking="render"を付けて読み込みます。
<script defer blocking="render" src="/js/app.js"></script>

Performance Insights で Cumulative Layout Shift (CLS)の値を図ってみると、以下のような結果になりました。

レンダリング方法Cumulative Layout Shift (CLS)
同期的に読み込む0.436
defer で読み込む0.436
async で読み込む0.436
blocking="render"を付けて読み込む0

濫用に注意

blocking="render"を使えばレンダリングブロックを意図的に行える事が分かりました。

ただし、レンダリングが遅くなるため、UXやSEO的には弱くなります。

レンダリング ブロッキング リソースを回避する | Publisher Ads Audits for Lighthouse | Google for Developers

https://developers.google.com/publisher-ads-audits/reference/audits/ad-render-blocking-resources?hl=ja

そのためblocking="render"が必要なリソースかどうか見極める必要があります。

まとめ

blocking="render"が使えるようになれば、簡単に FOUC を防ぐ事が出来ます。

執筆時では対応しているブラウザが少ないですが、非常に便利な機能なので対応ブラウザが増えて欲しいところです。

PerformanceResourceTiming API: renderBlockingStatus | Can I use... Support tables for HTML5, CSS3, etc

https://caniuse.com/mdn-api_performanceresourcetiming_renderblockingstatus

新しいメンバーを募集しています

Sena

Sena / Engineer

生涯に亘り技術を極めていきたい。