遅延読み込み

画像・iframe要素などの遅延読み込みを行い、パフォーマンス改善する機能についてご紹介します。
一般的には Lazy Load と呼ばれています。

Lazy Load とは

簡単に Lazy Load 機能を説明すると「必要な時にコンテンツをロードする機能」となります。よく見られる使用例としては、表示領域にない画像は最初読み込まず、スクロールして表示領域に入ったときに初めて画像をロードするなどがあります。

メリットとして表示領域以外のコンテンツはロードしないようになるため、最初のロード時にダウンロードするコンテンツ量が少なく済み、ページの表示速度のパフォーマンスが向上します。

デフォルトの設定

この機能の設定は、/js/config.jsの以下の箇所にあります。

lazyLoadMark: '.js-lazy-load',
lazyLoadConfig: {
    rootMargin: '10px 0px', // syntax similar to that of CSS Margin
    threshold: 0.1, // ratio of element convergence
   loaded: function(el) {
      el.addEventListener('load', function () {
        if (el.tagName === 'IMG') {
          var img = new Image();
          img.onload = function () {
            el.classList.add('loaded');
          }
          img.src = el.getAttribute('src');
        } else {
          el.classList.add('loaded');
        }
      });
      setTimeout(function () {
        el.classList.add('loading');
      }, 100);
    ACMS.dispatchEvent('acmsLazyLoaded', el);
  }
},

設定のカスタマイズ

config.jsのデフォルトの設定から設定を変更する場合は、適用しているテーマ内にJavaScriptファイルを別途作成し以下のように記述してください。詳しくは「組み込みJSについて:設定を編集する」を参照してください。

ACMS.Ready(function(){
  lazyLoadMark = '.js-lazy-load',
  lazyLoadConfig =  {
    rootMargin: '10px 0px', // syntax similar to that of CSS Margin
    threshold: 0.1, // ratio of element convergence
    loaded: function(el) {
      el.addEventListener('load', function () {
        if (el.tagName === 'IMG') {
          var img = new Image();
          img.onload = function () {
            el.classList.add('loaded');
          }
          img.src = el.getAttribute('src');
        } else {
          el.classList.add('loaded');
        }
      });
      setTimeout(function () {
        el.classList.add('loading');
      }, 100);
      ACMS.dispatchEvent('acmsLazyLoaded', el);
    }
  }
});

使い方

Ver. 2.11 の標準ユニットは、Lazy Load に対応されていますので、特にユニットは追加でカスタマイズする必要はありません。静的なソースコードやカスタムフィールド で Lazy Load する場合を確認していきましょう。

画像の場合

画像に Lazy Load を設定する場合の基本は、以下のように実装します。

<img class="js-lazy-load" src="/images/placeholder/image.svg" data-src="/media/{hoge@path}" alt="">


class属性 例:js-lazy-load
data-src属性 表示する画像のパス(例:/media/{hoge@path})
src属性 ローディング時に表示する画像を指定(例:/images/placeholder/image.svg)

※/images/placeholder/image.svg は systemテーマの中に入っています

画像の場合は srcset 属性(スクリーン幅によって読み込む画像を変える)を使いたい場合もあると思います。以下のように、 data-srcset属性 data-sizes属性 を使うことで可能になります。

<img class="js-lazy-load" src="/images/placeholder/image.svg" data-srcset="/media/{hoge@path}[resizeImg(640)] 640w, /media/{hoge@path}[resizeImg(1200)] 1200w" data-sizes="100vw" alt="">

iframeの場合

YouTubeなどコンテンツの埋め込みで iframe要素を使うことは多いと思います。 iframe要素の場合も簡単に Lazy Load に対応することができます。 画像と同じく data-src属性に読み込みたいコンテンツを指定するだけです。

<iframe class="js-lazy-load" width="640" height="360" data-src="https://www.youtube.com/embed/MwlwcmF0hwo?wmode=transparent&rel=0" frameborder="0" allowfullscreen></iframe>

Open Street Map、Google Mapの場合

a-blog cms 標準で入っている各種地図の組み込みJSも簡単に Lazy Load 対応できます。特に Google Map などは、有料化されアクセス数が気になりますが、Lazy Load 対応することでアクセス数を節約でき、Google Map を導入しやすくなります。

全て、data-lazy="true" を適用するだけで対応できます。

Open Street Map の場合

<div class="js-open-street-map" data-lazy="true" data-lat="35.185574" data-lng="136.899066" data-zoom="10" data-msg="test" style="width: 640px; height: 360px;"></div>

Google Map の場合

<img class="js-s2d-ready" data-lazy="true" src="//maps.googleapis.com/maps/api/staticmap?center=35.185574,136.899066&zoom=10&size=640x360&maptype=roadmap&markers=35.185574,136.899066&key=AIzaSyDtJZq2qv89P-tRxMoBzmnrV_17vlw5Zl8" alt="test" width="640" height="360" title="クリックで地図が動かせるようになります。">

Ver. 3.1.26 リリースのお知らせ


この記事では、2024年9月26日にリリースした Ver. 3.1.26 の修正内容について紹介いたします。

現在お困りの問題に該当する項目がありましたら、お早めにバージョンアップのご検討をお願いいたします。

Ver. 3.1.26 リリースノート

修正点

  • CMS-6923 互換性を保った状態で、jquery.cookie.js を使用しないように修正
  • CMS-6926 Ver. 3.1.23 〜 Ver. 3.1.25で ユニットを非表示にすると、それ以下のユニットも非表示になってしまう問題を修正

Ver. 3.0.40 リリースノート

修正点

  • CMS-6924 互換性を保った状態で、jquery.cookie.js を使用しないように修正

Ver. 2.11.69 リリースノート

修正点

  • CMS-6925 互換性を保った状態で、jquery.cookie.js を使用しないように修正

主なリリースノートの詳細な内容

CMS-6923 互換性を保った状態で、jquery.cookie.js を使用しないように修正

jquery.cookie.jsというファイル名が原因で、WAF(Web Application Firewall)によってブロックされ、管理画面のJavaScriptが正常に動作しない問題が確認されました。 現在、Xserverで「XSS対策のWAF」をONにしている環境でこの問題が再現することが確認されています。

今回の修正による互換性に影響はありませんので、アップデート以外の作業は必要ありません。

応急処置

アップデートがすぐ難しいという方は以下記事で対応方法を解説していますので、こちらをご覧ください。

https://developer.a-blogcms.jp/blog/news/xserver-waf.html

CMS-6926 Ver. 3.1.23 〜 Ver. 3.1.25で ユニットを非表示にすると、それ以下のユニットも非表示になってしまう問題を修正

Ver. 3.1.23 から Ver. 3.1.25 で、ユニットを1つでも非表示にすると、それ以下のユニットも非表示になってしまう問題を修正しました。 クリティカルな問題になりますので、該当バージョンをお使いの方はアップデートをお願いします。


ユニットの非表示

ユニットの非表示


該当バージョン

  • Ver. 3.1.25
  • Ver. 3.1.24
  • Ver. 3.1.23

応急処置

該当バージョンをお使いで、アップデートがすぐ難しいという方は以下の方法で応急処置できますのでご確認ください。

ablogcms/php/Services/Unit/Rendering/Front.php: 45行目付近

修正前

if (!$isDisplayInvisibleUnit && 'hidden' === $unit->getAlign()) {
    return; // 非表示ユニット
}

修正後

if (!$isDisplayInvisibleUnit && 'hidden' === $unit->getAlign()) {
    continue; // 非表示ユニット
}

「return」を「continue」に変更ください。


最後に

該当する問題がありましたら、お早めにバージョンアップのご検討をお願いいたします。
また、迅速にご報告いただいたユーザーの皆さま、誠にありがとうございました。

今後もご報告いただいた内容に対して真摯に受け止め修正と改善を行ってまいります。
今後ともどうぞよろしくお願いいたします。

テーブルの編集

テーブルユニットにも採用されているテーブルの編集のユーザーインターフェースです(Ver.2.7.0 より)。
カスタマイズ次第でブログやカテゴリー、エントリーのカスタムフィールドとしても利用可能です。


テーブル見出しとテーブルの内容それぞれがグラフィカルに入力できるようになっている

テーブル編集UIのイメージ


使い方

js/config.js に設定されている「aTableMark, aTableDestMark, aTableFieldMark」に設定されているクラスを利用して以下のようなHTMLを記述します。 IFブロックのELSEの中には初期値のテーブルを好きに記述することができます。

<div class="js-editable-table-field" style="background-color:#ddd;padding:10px;">
  <div class="js-editable-table">
    <!-- BEGIN_IF [{table}[delnl]/nem] -->
    {table}[raw]
    <!-- ELSE -->
    <table>
      <tr>
        <th>サンプル</th>
        <th>サンプル</th>
      </tr>
      <tr>
        <td>サンプル</td>
        <td>サンプル</td>
      </tr>
    </table>
    <!-- END_IF -->
    <input type="hidden" class="js-editable-table-dest" value="{table}" name="table">
    <input type="hidden" name="field[]" value="table">
  </div>
</div>

デフォルトの設定

この機能の設定は、/js/config.jsの以下の箇所にあります。設定を変更する場合は、適用しているテーマ内にJavaScriptファイルを別途作成してください。詳しくは「組み込みJSについて:設定を編集する」を参照してください。

aTableMark: '[class^=js-editable-table]',
// エントリーの編集画面でユニットにこのクラスを指定することでテーブルユニットとして動作します。
aTableDestMark: '.js-editable-table-dest',
// テーブルで入力されたHTMLの結果をvalueとして格納することができます。
aTableFieldMark: '.js-editable-table-field',
/*
カスタムフィールドなどでテーブル編集用のUIを表示するには上の
aTableMarkで指定された要素をさらにこのセレクターで囲ってあげる必要があります
*/
aTableConf: {
  align: {
		default: 'acms-cell-text-left',
		// セルにデフォルトで付与されたクラス
		left: 'acms-cell-text-left',
		// 左寄せを設定した際に実際にセルに付与されるクラス
		center: 'acms-cell-text-center',
		// 中央寄せを設定した際に実際に付与されるクラス
		right: 'acms-cell-text-right'
		// 右寄せを指定した際に実際に付与されるクラス
  },
  btn: {
		group: 'acms-admin-btn-group acms-admin-btn-group-inline',
		//テーブル編集UIのボタングループに付与されるクラス
		item: 'acms-admin-btn',
		//テーブル編集UIのボタンに付与されるクラス
		itemActive: 'acms-admin-btn acms-admin-btn-active'
		//テーブル編集UIのボタンがアクティブの際に付与されるクラス
  },
  icon: {
		alignLeft: 'acms-admin-icon-text-left',
		//左寄せアイコンに付与されるクラス
		alignCenter: 'acms-admin-icon-text-center',
		//中央寄せアイコンに付与されるクラス
		alignRight: 'acms-admin-icon-text-right',
		//右寄せアイコンに付与されるクラス
		undo: 'acms-admin-icon-undo',
		//undoアイコンに付与されるクラス
		merge: 'acms-admin-icon-merge',
		//mergeアイコンに付与されるクラス
		split: 'acms-admin-icon-split',
		//分割アイコンに付与されるクラス
		source: 'acms-admin-icon acms-admin-icon-source',
		//ソースアイコンに付与されるクラス
	td: '',
	//tdアイコンに付与されるクラス
	th: ''
	//thアイコンに付与されるクラス
  }
},
aTableSelector: [
	/*
		右寄せ、左寄せ、中央寄せ以外に付与したいクラスがある場合にここに値を追加できます
		label: セレクターに表示される内容, value: 選択時にセルに付与されるクラス
	*/
  { label: ACMS.i18n('a_table.not_newline'), value: 'acms-cell-text-nowrap acms-admin-cell-text-nowrap' },
  { label: ACMS.i18n('a_table.bold'), value: 'acms-cell-text-bold acms-admin-cell-text-bold' },
  { label: ACMS.i18n('a_table.top_alignment'), value: 'acms-cell-text-top acms-admin-cell-text-top' },
  { label: ACMS.i18n('a_table.center_alignment'), value: 'acms-cell-text-middle acms-admin-cell-text-middle' },
  { label: ACMS.i18n('a_table.bottom_alignment'), value: 'acms-cell-text-bottom acms-admin-cell-text-bottom' }
]