はじめに
みなさま、JavaScriptコードの呼び出しはどうしていますか?
以下のようにasync
属性やdefer
属性を付けることによって、JavaScriptによるパーサーブロッキングを防ぐことが出来ます。
<script defer async src="/js/app.js"></script>
大体のJavaScriptコードを呼び出す際はこれで良いのですが、一部例外があります。
その一つがWeb ComponentsにおけるCustom Elementsの定義時です。
Custom Elementsの定義時に注意すること
Custom Elementsの定義時とは、つまりcustomElements.define()
のことです。
例えばシンプルなWeb Componentsのコードを/js/app.js
に書いたとします。
'use strict';
const html = '<div style="display: flex; justify-content: center; align-items: center; color: white; background-color: #222; height: 1000px;">WebComponentsで動的に生成したHTML</div>';
class FrSample extends HTMLElement {
constructor() {
super();
this._root = this.attachShadow({mode: 'closed'});
}
render() {
this._root.innerHTML = `${html}`;
}
connectedCallback() {
this.render();
}
}
customElements.define('fr-sample', FrSample);
これを踏まえて以下のことに気を付けましょう。理由は後述します。
asyncまたはdeferでコードを呼び出さない
前述した通りです。
<script defer async src="/js/app.js"></script>
Custom Elementsを使うコードより前に定義する
Custom Elementsを使う前に、Custom Elementsを定義しましょう。
基本的には<head>
内に書いておけば問題ありません。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta name="viewport" content="width=device-width, viewport-fit=cover"/>
<meta charset="UTF-8"/>
<title>SAMPLE</title>
**<script src="/js/app.bundle.js"></script>**
</head>
<body>
**<fr-sample></fr-sample>**
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta name="viewport" content="width=device-width, viewport-fit=cover"/>
<meta charset="UTF-8"/>
<title>SAMPLE</title>
</head>
<body>
**<fr-sample></fr-sample>**
**<script src="/js/app.bundle.js"></script>**
</body>
</html>
イベントを使って呼び出さない
何かの癖で、DOMContentLoadedリスナー内に書かないようにしましょう。
document.addEventListener('DOMContentLoaded', function () {
customElements.define('fr-sample', FrSample);
});
jQueryについても同じです。
// import $ from 'jquery';
$(function () {
customElements.define('fr-sample', FrSample);
});
$(document).ready(function () {
customElements.define('fr-sample', FrSample);
});
パーサーブロッキングさせる理由
理由は簡単です。
Web Componentsが呼び出された際に、Layout Shift
と判定される可能性があるからです。 結果的にCore Web VitalsのCumulative Layout Shift(CLS)が悪くなってしまいます。
推奨する管理方法
パーサーブロッキングが必要なJavaScriptコードは、他のコードとは別ファイルにしましょう。
**<script defer async src="/js/common.bundle.js"></script> <!-- パーサーブロッキング不要 -->**
**<script src="/js/app.bundle.js"></script> <!-- パーサーブロッキング必要 -->**
コードが短い場合では、インライン化してしまうのもアリです。
**<script defer async src="/js/common.bundle.js"></script>**
**<script>'use strict';const html='<div style="display: flex; justify-content: center; align-items: center; color: white; background-color: #222; height: 1000px;">WebComponentsで動的に生成したHTML</div>';class FrSample extends HTMLElement{constructor(){super();this._root=this.attachShadow({mode:'closed'})} render(){this._root.innerHTML=``} connectedCallback(){this.render()}} customElements.define('fr-sample',FrSample)</script>**
まとめ
Core Web Vitalsの中でも、特にCLSはサーバーの処理性能が絡みにくいところです。そのため対策は楽な方だと思います。
常にLayout Shift
が起きないように、注意深くコーディングしていきましょう。
新しいメンバーを募集しています
Sena / Engineer
生涯に亘り技術を極めていきたい。