1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

HTMLAdvent Calendar 2023

Day 3

blocking="render"でスクリーンへのコンテンツのレンダリングをブロック?

Last updated at Posted at 2023-12-02

はじめに

<link><script><style>に、
スクリーンへのコンテンツのレンダリングをブロックする
blocking="render"という属性がChromeに追加されていることに最近気付きました。
caniuse.comによるとChrome105から追加されたようです。

ローカルにWebサーバーを起動して、
DevTools の Network の Panel で キャッシュを無効化して、
DevTools の Performance の Panel で確認してみます。

<script>

以下コードを試してみます。

:notebook_with_decorative_cover: script.js
script.js
/*
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117 
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954 
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
*/
:notebook_with_decorative_cover: sample.script.html
sample.script.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js"></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.script.render.html
sample.script.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js" blocking="render"></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.script.defer.render.html
sample.script.defer.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js" defer blocking="render"></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.script.defer.html
sample.script.defer.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js" defer></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.script.async.render.html
sample.script.async.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js" async blocking="render"></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.script.async.html
sample.script.async.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <script src="script.js" async></script>
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>

上記コードの違いは上から順に、
<script src="script.js">に対して、
以下属性を付与したりしたものです。

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

それぞれ以下のようなタイミングでの動作でした。
※以下script.jsのロード完了を SL と略して記載します。

<script src="script.js"></script>
// [SL] >> [DCL] > [FP] = [FCP] = [LCP] > [L]
<script src="script.js" blocking="render"></script>
// [SL] >> [DCL] > [FP] = [FCP] = [LCP] > [L]
<script src="script.js" defer blocking="render"></script>
// [SL] >> [DCL] > [FP] = [FCP] = [LCP] > [L]
<script src="script.js" defer></script>
// [FP] = [FCP] = [LCP] >> [SL] >> [DCL] > [L]
<script src="script.js" async blocking="render"></script>
// [DCL] >> [SL] >> [L] > [FP] = [FCP] = [LCP]
<script src="script.js" async></script>
// [DCL] > [FP] = [FCP] = [LCP] >> [SL] >> [L]

上記結果から分かるのは、
blocking="render"の属性を付与すると、
スクリーンへのコンテンツのレンダリングをブロックするのではなく、
スクリーンへのコンテンツのレンダリングをブロックする処理が追加される、
という感じのようです。

ですので、

<script src="script.js"></script>は、
そもそもレンダリングブロックな動作なので、
blocking="render"の属性を付与しても、
動作的には意味はないのかなと思われます。

<script src="script.js" defer></script>は、
[DCL]でブロックされるので、
blocking="render"の属性を付与すると、
[FP] [FCP] [LCP] もブロックされるようになるようで、結果、
[DCL] [FP] [FCP] [LCP] でブロックされるようになるようです。

<script src="script.js" async></script>は、
ノンブロッキングな動作なので、
blocking="render"の属性を付与すると、
[FP] [FCP] [LCP] でブロックされるようになるようです。

<link>

続いて、
以下コードを試してみます。

:notebook_with_decorative_cover: style.css
style.css
/*
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117 
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954 
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
*/
:notebook_with_decorative_cover: sample.link.html
sample.link.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.link.render.html
sample.link.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <link href="style.css" rel="stylesheet" blocking="render">
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.link.preload.html
sample.link.preload.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>
:notebook_with_decorative_cover: sample.link.preload.render.html
sample.link.preload.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
    <link rel="icon" href="data:,">
    <link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" blocking="render">
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
  </body>
</html>

上記コードの違いは上から順に、
<link href="style.css">に対して、
以下属性を付与したりしたものです。

    <link href="style.css" rel="stylesheet">
    <link href="style.css" rel="stylesheet" blocking="render">
    <link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
    <link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" blocking="render">

それぞれ以下のようなタイミングでの動作でした。
※以下style.cssのロード完了を SL と略して記載します。

<link href="style.css" rel="stylesheet">
/* [DCL] >> [SL] > [L] > [FP] = [FCP] = [LCP] */
<link href="style.css" rel="stylesheet" blocking="render">
/* [DCL] >> [SL] > [L] > [FP] = [FCP] = [LCP] */
<link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
/* [DCL] > [FP] = [FCP] = [LCP] > [L] >> [SL] */
<link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" blocking="render">
/* [DCL] > [FP] = [FCP] = [LCP] > [L] >> [SL] */

<link href="style.css" rel="stylesheet">は、
<script src="script.js"></script>同様に、
そもそもレンダリングブロックな動作なので、
blocking="render"の属性を付与しても、
動作的には意味はないのかなと思われます。

<link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">は、
ノンブロッキングな動作なので、
blocking="render"の属性を付与すると、
[FP] [FCP] [LCP] でブロックされるようになると思われますが、
ノンブロッキングな動作なままです...
何故でしょう...

<link rel="preload" as="fetch" blocking="render">

以下コードを試してみます。

:notebook_with_decorative_cover: asap.html
asap.html
<p>asap</p>
<!--
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117 
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954 
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
-->
:notebook_with_decorative_cover: lazy.html
lazy.html
<p>lazy</p>
<!--
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117 
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954 
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
-->
:notebook_with_decorative_cover: sample.link.preload.fetch.render.html
sample.link.preload.fetch.render.html
<!DOCTYPE html>
<html lang="ja-JP">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="preload" as="fetch" crossorigin="anonymous" onload="console.log(`preloaded ${this.href}`)" href="asap.html" blocking="render">
    <link rel="preload" as="fetch" crossorigin="anonymous" onload="console.log(`preloaded ${this.href}`)" href="lazy.html">
    <title>sample</title>
    <link rel="icon" href="data:,">
  </head>
  <body>
    <header><p>header</p></header>
    <main><p>main</p></main>
    <footer><p>footer</p></footer>
    <script>(async () => document.querySelector('header').append(document.createRange().createContextualFragment(await (await fetch('asap.html')).text())))();</script>
    <script>(async () => document.querySelector('footer').append(document.createRange().createContextualFragment(await (await fetch('lazy.html')).text())))();</script>
  </body>
</html>

asap.htmlがロード完了までレンダリングブロックされ、
asap.htmlがロード完了したところで画面の描画、
lazy.htmlがロード完了したところで画面の更新、
となる想定でしたが、
実際は、
sample.link.preload.fetch.render.htmlの処理完了したところで画面の描画、
asap.htmlがロード完了したところで画面の更新、
lazy.htmlがロード完了したところで画面の更新、
となります...
何故でしょう...

<link rel="preload" blocking="render">

mdnの情報だけですと心もとないので、
仕様を検索するとproposalがあり、
冒頭に、

blocking="render"の属性は、
<link rel="preload">と、
<link rel="modulepreload">から削除しました。
Webフォントのユースケース向けに、
CSSベースのソリューションを追求していきます。

というような事が書かれており、
<link rel="preload">では、
blocking="render"は出来ないようです。orz

また、
blocking="render"が使用可能なのは、
proposalによると<head>内のみのようです。

<link media="print" blocking="render">

<link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
<link href="style.css" rel="stylesheet" media="print" onload="this.onload=null;this.media='all'">

<link rel="preload">を使用せずとも、
<link media="print">を使用すれば、
ノンブロッキングな動作になるので、

<link href="style.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" blocking="render">
<link href="style.css" rel="stylesheet" media="print" onload="this.onload=null;this.media='all'" blocking="render">

<link rel="preload">を使用せず、
<link media="print">を使用して、
blocking="render"の属性を付与すれば上手くいくのでは?
と試してみましたが、
ノンブロッキングな動作のままでした...

<style>

未調査。

おわりに

<script>でのblocking="render"に関しては、
<script src="script.js" async blocking="render">は使い道があるかもしれませんが、
<script src="script.js" defer blocking="render">は微妙です。
<script src="script.js">とほぼ同様の動作に結局なると思われるので...

<link>でのblocking="render"に関しては、
<link rel="preload" blocking="render">が出来ないのが、
個人的には厳しいという感想です。

あと、
proposal の possible extensions に記載のある、
blocking="domcontentloaded"が出来るようになると有難いけど、
proposal 自体の熱は既に冷めてしまっているようなので期待薄でしょうか...

proposal
proposal-v3

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?