amp imgタグで画像の遅延読み込みの対応とショートコード作成

こんにちはnasustです。

Google Page Speed Insightsの測定で画像を遅延読み込みに対応して下さい、 と改善案を表示されることがあります。

遅延読み込みに対応するにはimgタグにloading="lazy"を設定することで可能です。

しかし現時点で対応しているブラウザはChrome 75以上のみです。 またGoogle Page Speed Insightsも対応していなので点数が上がりません。

そこでお手軽に遅延読み込み対応するにはAMP(Accelerated Mobile Pages)で利用できるamp-imgタグを使用します。 このタグはカスタムタグで通常のWEBページでも利用できます。

AMPとは

Accelerated Mobile Pagesの略です。要するにモバイルページを高速で表示する為のフレームワークです。

AMPが高速であるのは、レンダリングブロックの回避、リソースのキャッシュなど高速化のための技術で開発されているからです。

そして AMPのフレームワークは通常のページでも利用できます。

AMPはTwitterやInstagram、YouTubeなどの埋め込みに対応しています。各サービスで提供されている埋め込み方法は重いです。 ですがAMPのフレームワーク使用することで埋め込みも高速化できます。

AMPの高速化の概要は以下のページで解説されています。

How AMP works - amp.dev

以下のページでAMPのデモを確認できます。 デモで確認すると色々なメディアがリッチに表現されています。 ブログで利用するには、かなり有能じゃないでしょうか。

Examples - amp.dev

各種コンポーネントの利用方法は以下のページで解説されています。

Components - amp.dev

AMP対応ブラウザは以下のページで確認できます。

AMP Supported Browsers - amp.dev

カスタムタグとは

独自のタグを定義できます。カスタムタグはブラウザでサポートされています。 HTML5 validatorでも問題ありません。

HTMLの仕様としてはHTMLUnknownElementとして扱われます。

HTML Standard
HTMLUnknownElement - Web API | MDN

AMPとHugo

HugoはAMPページのジェネレーションに対応しています。 しかし、テンプレートのMarkdownの内容を出力する.Page.ContentはAMPページを考慮してくれません。 ですのでMarkdownはAMPページで禁止している要素を考慮して書かないと問題が発生します。

その為、Markdownで画像を表示する場合はamp-imgを使用するショートコードで対応します。

Hugoのショートコードとは

ショートコードとは、htmlのテンプレートをMarkdownの文中に短いコードで呼び出す事ができます。 WordPressのショートコードと同じですね。

layout/shortcodesにテンプレートを設置します。

Markdownの文中に{{< テンプレート名 >}}と記述することでショートコードを利用できます。

Shortcodes | Hugo

AMP導入手順

通常のページでamp-imgの導入手順を解説します。

ampのJavaScript読み込み

htmlのhead要素かbodyの最後にjsファイルを設置します。 asyncで読み込むのでレンダリングブロックしません。

<script async src="https://cdn.ampproject.org/v0.js"></script>

Hugoのamp-imgのショートコードを作成する

/layout/shortcodes/img.htmlに以下のテンプレートを作成します。

{{ $class := default "" (.Get "class") }}
{{ $layout := default "responsive" (.Get "layout") }}

{{ $scale := default 0.0 (.Get "scale") }}
{{ $thumbnail := default "true" (.Get "thumbnail") }}
{{ $thumbnail_width := default 620 (.Get "thumbnail_width") }}
{{ $thumbnail_width = int $thumbnail_width }}
{{ $src := .Get "src" }}

{{ if $scale }}
    {{ $scale = float $scale }}
{{ end }}

{{ $image := $.Page.Resources.GetMatch $src }}
{{ $width := $image.Width }}
{{ $height := $image.Height }}

<figure class="{{$class}}">
    {{ $href := $src }}
    {{ with $image }}
        {{ if eq $thumbnail "true" }}
            {{ if $scale }}
                {{ $width = mul $width $scale }}
                {{ $width = int $width }}
                {{ $image = $image.Resize (printf "%dx Lanczos" $width ) }}
            {{ else }}
                {{ $image = $image.Resize (printf "%dx Lanczos" $thumbnail_width ) }}
            {{ end }}
            {{ $src = $image.Permalink }}
            {{ $width = $image.Width }}
            {{ $height = $image.Height }}
        {{ else if $scale }}
            {{ $width = mul $width $scale }}
            {{ $width = int $width }}
            {{ $height = mul $height $scale }}
            {{ $height = int $height }}
        {{ end }}
    {{ end }}
    {{ with .Get "link" }}
        {{ $href = . }}
    {{ end }}

    <a href="{{ $href | safeHTMLAttr }}" target="_blank" rel="noopener noreferrer">
        <amp-img
            src="{{ $src }}" 
            width="{{ $width }}"  
            height="{{ $height }}" 
            layout="{{ $layout }}" 
            {{ if $scale }}
                style="max-width:{{ $width }}px; max-height:{{$height}}px;"
            {{ end }}
        >
        </amp-img>
    </a>
</figure>

amp-imgをfigureで囲っています。 ページリソースから画像を取得してサムネイルを生成しています。 ページリソースに無ければ、外部の画像として処理します。 その場合はwidthとheightの指定が必須です。

使用例

文中に{{< img src=“image.jpg” >}}で上記のテンプレートが表示されます。

iOS、Android、Web、APIサーバーなどのフロントエンド・バックエンドを開発するソフトウェアエンジニアです。 UI/UXが好きです。かっこいいUIやWebデザインを眺めるのが趣味です。 このブログはソフトウェア開発関係の内容を記事にしています。
web service:
GitHubQiitaTwitterはてなブログ
handle name:
nasust
real name:
hideki mori
job:
ソフトウェアエンジニア
develop:
target: ios, android, web page, single page application, api server, system service, cli tool, linux embedded device

lang: c/c++, go, swift, objective-c, java, kotlin, typescript, dart, javascript, ruby, python, php

tool: vscode, xcode, android studio, photoshop, vim, docker