Web

たくさんの Web Components を利用するページを改善する

投稿日:2021年10月15日 更新日:

1. はじめに

昨日の記事では、Web Components を使って複数のコンポーネントを 1つのWebページ上に作成する方法を紹介しました。

Web Components

1つのWebページに複数のHTML要素サンプルを記述する

2021.10.14

今回は、そこで紹介したコードを改善します。

2. 改善点その1(CLS)

まず、CLS (Cumulative Layout Shift) の問題に対処します。

昨日の内容の場合、Webページがレンダリングされる前の時点で、Web Component の表示サイズを計算するための情報がないために、必要なサイズが確保されないまま最初のレンダリングが行なわれてしまいます。そしてその後、Web Component が画面上に適用される段階になってはじめて表示サイズが決定するため、「今まで何もなかった場所に、Web Component が表示され、その下の要素の位置がずれる」現象が発生してしまいます(これが CLS です)。

この問題に対応するには、カスタム要素の幅と高さを CSS で指定すればよいのですが、カスタム要素に対して width と height を指定しても効かないので、カスタム要素をラッパー要素で囲んでおき、ラッパー要素の方に大きさを指定しておきます。

HTML

<div class="wrapper">
  <my-element></my-element>
</div>

CSS

div.wrapper {
  width: 400px;
  height: 225px;
}

aspect-ratio プロパティを使ってもよいです。

div.wrapper {
  width: 400px;
  aspect-ratio: 16 / 9;
}

3. 改善点その2(Web Component の遅延読み込み)

次に、ファーストビュー(最初に表示される画面の範囲)より下にある Web Component を、必要になったとき(画面がスクロールされたとき)になってはじめて読み込ませることで、Webページアクセス時の転送データ量を少なくすることができます(<img>要素の loading=lazy 属性と同じことをさせるイメージです)。

但し、ファーストビュー上に表示される(可能性のある)Web Component を遅延読み込みすると、LCP (Largest Contentful Paint) というパフォーマンス指標の値が悪化する可能性があります。簡単に言うと、アクセス時の画面表示が遅くなるかもしれない、ということです。ですので、厳密にはそちらは遅延読み込みさせない方がよいです。とはいえ、たいして影響がないのならまとめて遅延読み込みでもよいと思います。

以下が、遅延読み込みのサンプルコードになります。遅延せずに JavaScript ファイルをインポートするコードは削除します(ファーストビュー上の Web Component を表す JavaScript ファイルの読み込みは残しておいてもよいです)。このコードは、<body>タグ内の最後あたりに追記します。

<script type="module">
// querySelectorAll()の引数をうまく調整して、処理の対象とするカスタム要素を取得します
let targetElements = [].slice.call(document.querySelectorAll('main > div > *'));

// コールバック関数を登録して、IntersectionObserver のオブジェクトを生成します
let myObserver = new IntersectionObserver((entries, observer) => {
  // 対象となる画像要素毎に処理を行います
  entries.forEach((entry) => {
    // この要素が画面に入ってきた場合
    if (entry.isIntersecting) {
      // この要素を画面に追加する
      let myElm = entry.target;
      let tagName = myElm.localName; // カスタムタグの名前
      // JavaScriptファイルをインポートします
      // カスタムタグの名前が、対応するJavaScriptファイル名になっている前提です
      import(`./${tagName}.js`)
        .then((module) => {
          //console.log(module.default);
          // インポートしたモジュールが、module にセットされています
          // JavaScript ファイルで定義したクラスをカスタムタグ名に紐付けます
          customElements.define(tagName, module.default);
        })
        .catch(err => {
          console.log(err);
          });

      // 表示したカスタムタグは観察対象から外します
      myObserver.unobserve(myElm);
    }
  });
});
targetElements.forEach((elm) => {
  // 各要素の観察を開始します
  myObserver.observe(elm);
});
</script>
  • Intersection Observer API を使って、観察対象となる要素が画面に入ってきそうになったら、JavaScriptファイルをインポートしています。
  • なるべくコメントに、何をやっているのか書きました。

3. おわりに

2つの改善点を紹介しました。

2つ目は大変そうに思えるかもしれませんが、これくらいのコード量で遅延読み込みが実現できるのであれば、少し頑張ってみる価値はあると思います。

4. 参考

5. 関連

Web

Intersection Observer API を使った画像の遅延読み込み

2019.03.29

📂-Web

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Chrome

Chrome: ツールバー上の拡張機能アイコンをメニューに移動させる方法

Chromeで、ツールバー上の拡張機能アイコンをメニューに移動させる方法について説明します。

DokuWiki

DokuWiki: Layout Switcher Plugin

DokuWiki用プラグイン「Layout Switcher Plugin」のページです。 目次1. 概要2. インストールと設定(1) プラグインファイルのダウンロード(2) プラグインをサーバーに …

Web

AMP for WordPress プラグインを使って WordPressサイトをAMP対応する手順

目次1. AMP とは?なぜ、AMP が必要なのか?AMP フレームワーク1. AMP HTML2. AMP JS3. AMP キャッシュその他2. AMP for WordPress プラグインにつ …

WordPress

【WordPress】JP Markdownプラグインが code タグの属性を削除する問題への対応方法

目次1. 現象2. 原因3. 対応方法 1. 現象 WordPress の JP Markdown プラグインを使っていると、以下のような (<pre> タグを伴わない単独の) <c …

Web

閲覧しているウェブページで利用されている HTTP のバージョンを確認する方法

ウェブブラウザで ウェブサイトを閲覧している際、HTTP のどのバージョンが使われているのか確かめる方法を紹介します。 目次Chrome の場合FirefoxEdge Chrome の場合 (1) ウ …