はじめに
<link>
と<script>
と<style>
に、
スクリーンへのコンテンツのレンダリングをブロックする
blocking="render"
という属性がChromeに追加されていることに最近気付きました。
caniuse.comによるとChrome105から追加されたようです。
ローカルにWebサーバーを起動して、
DevTools の Network の Panel で キャッシュを無効化して、
DevTools の Performance の Panel で確認してみます。
DevTools Network
DevTools Network
Disable cache
DevTools Performance
DevTools Performance
FP / FCP / LCP / DCL / L
<script>
以下コードを試してみます。
script.js
/*
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
*/
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>
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>
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>
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>
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>
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>
続いて、
以下コードを試してみます。
style.css
/*
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
*/
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>
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>
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>
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">
以下コードを試してみます。
asap.html
<p>asap</p>
<!--
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
-->
lazy.html
<p>lazy</p>
<!--
3.
141592653589 793238462643 383279502884 197169399375 105820974944 592307816406 286208998628 034825342117
067982148086 513282306647 093844609550 582231725359 408128481117 450284102701 938521105559 644622948954
以下略(ロードに時間が掛かるファイルサイズになる行数分記載)
-->
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
proposal
proposal-v3 possible extensions