Hexoでnative-lazy-loadingに対応する
フィギュアレビュー記事の表示速度が遅いので、
ブラウザnativeのlazy-loading(遅延読み込み)
に対応する。
自前のscriptでloading
, width
, height
属性を付与する作戦。
長くなっちゃったので、記事は折りたたんである↓。
手順
まず、image-size
を使うので、npm install image-size
しておく。
次に、↓のscriptをthemes/***/scripts
に置く。
scripts
フォルダに置いたjsファイルはhexoのgenerate時に自動で実行される。
// This script refers to `hexo-native-lazy-load`.
// <https://github.com/fengkx/hexo-native-lazy-load>
// require
const sizeOf = require("image-size");
const path = require("path");
const fs = require("fs");
const log = hexo.log;
// config
const regex = /<img[^>]+src=\"(.+?)\"[^>]*>/gm;
// function
const mylog = (...args) => {
log.debug(path.basename(__filename), ": ", ...args);
};
const replace = (html, rootPath) => {
return html.replace(regex, (s, relativePath) => {
mylog('s: "' + s + '".');
if (s.indexOf('loading="lazy"') !== -1) {
mylog('Already added `loading="lazy"`. Do nothing.');
return s;
}
const imagePath = path.join(rootPath, relativePath);
mylog("image path: " + imagePath);
if (rootPath !== "" && fs.existsSync(imagePath)) {
const dimensions = sizeOf(imagePath);
mylog("width: " + dimensions.width + ", height: " + dimensions.height);
return (
s.substring(0, 4) +
' loading="lazy"' +
` width="${dimensions.width}"` +
` height="${dimensions.height}"` +
s.substring(4, s.length)
);
} else {
mylog("Not found image.");
return s.substring(0, 4) + ' loading="lazy"' + s.substring(4, s.length);
}
});
};
// main
hexo.extend.filter.register("after_post_render", function (data) {
mylog('replace: "' + data.title + '".');
data.content = replace(data.content, hexo.source_dir);
return data;
});
次に、css(stylus)の修正もいる。↓のファイルをいじる。 (landscape以外を使ってる人は適宜読み替えてね。)
themes/landscape/source/css/_partial/article.styl
ツリー構造で示すと、↓をいじる。
.article-entry
img, video
max-height: 100vh
の設定を無効化(コメントアウト)する。
最終的には↓のようになってる。
(max-height
以外のコメントアウトは無視して。)
img, video
max-width: 100%
// max-height: 100vh
// width: auto
height: auto
// object-fit: contain
display: block
margin: auto
最後に、clean&generateすればOK。
解説と蛇足
jsの中身は hexo-native-lazy-load pluginのほぼパクり。
hexo-native-lazy-load
pluginそのままだと、
post_asset__folder
を有効にしないと、うまく動作しない。
<img>
のwidth
とheight
を入力してくれない。
この記事のjsはpost_asset_folder
が無効でも動作するように改良した(つもり)。
やってることは、大雑把に↓の2つ。
loading="lazy"
を付与image-size
で画像サイズ取得して、width
,height
属性を付与
ちなみに、pluginとして公開する予定はなし。体裁を整えるのがめんどいため。
cssについては、本当はmax-height: 100vh
の設定も有効のままにしておきたかった。
だけど、lazy-loadingで有効にすると、aspect比が崩れちゃうのよね…。
なんでaspect比を固定する属性とかがcssにないんだろう。不思議。
なお、lazy-loadingが効いてるかどうかは、chromeのデバッガを使えば分かる。
Network
タブで、スクロールするごとに画像がloadされてれば成功。
↓の例だと、prisma_klangfest_chloe_3.webp
が遅延読み込みした画像。
他、 先駆者の方の記事 も参考にしてる。 感謝感謝。
これで、フィギュアレビュー記事の体感表示速度が上がったはず。 Netlifyくん、転送速度が結構遅い。 無料のホスティングサービスなのでしょうがない。工夫でカバー。