![今のところinput[type=”number”]を使わない方が良い理由と代替案 アイキャッチ](https://www.fourier.jp/storage/blog/post-outline/jLh85zUW8RaWiVlX9MATwpSprFDEYZw5.jpg)
はじめに
みなさま、 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=`${html}`} connectedCallback(){this.render()}} customElements.define('fr-sample',FrSample)</script>**
まとめ
Core Web Vitalsの中でも、特にCLSはサーバーの処理性能が絡みにくいところです。そのため対策は楽な方だと思います。
常に Layout Shift
が起きないように、注意深くコーディングしていきましょう。