ザリガニデザインオフィス

imageminとNetlifyで 画像ファイルを自動最適化のサムネイル

imageminとNetlifyで 画像ファイルを自動最適化

このサイトはそこまで画像を多用しているサイトではないですが、画像を最適化することはページ読み込み、ひいてはSEO上でも重要になってきています。当サイトでは、node.jsのsharp, imageminというライブラリとNetlifyのビルド設定を用いて画像の最適化を自動で処理するようにしています。

この記事ではimageminの細かい使い方などは解説していませんので、具体的な方法などは「imagemin 使い方」などで検索してください。

画像最適化の手法

当サイトで使っている画像最適化手法は

  • 初期表示画像の縮小(元画像の半分)
  • 画像ファイルそのものの軽量化(圧縮)

初期表示画像は遅延読み込みを使って、スクロール時に本画像へ差し替えます。詳しくはこちらの『markdown-itをカスタマイズして遅延ロードを実装する』に書いてます。

基本構成と処理の流れ

以下のようなフォルダ構成になっています。(実際はもうちょっと細かい構成になっています)

┬─ images
└─ images_src

上記のimages_srcフォルダが元画像、imagesフォルダが実際にページに表示される画像になります。画像を作成したら、このimages_srcフォルダに格納します。その状態で最適化処理にかければimagesフォルダへ画像が出力されます。

最適化処理は次のような流れで実行されます。

  1. 元画像をimagesフォルダへコピー
  2. 画像を半分に縮小したものを作成
  3. 縮小された画像、コピーされた元画像を圧縮軽量化

画像のコピー

まずは元画像をコピーします

const fs = require("fs-extra");
const path = require("path");

const src_image_path = path.resolve(__dirname, "PATH/TO/images_src");
const dist_image_path = path.resolve(__dirname, "PATH/TO/images");

await fs.copySync(src_image_path, dist_image_path);

画像のリサイズ

画像のリサイズにはSharpというライブラリを使っています。

const sharp = require("sharp");

function get_file_extension(format) {
  switch (format) {
    case "jpeg":
      return "jpg";
      break;
    default:
      return format;
  }
}

const name = "FILE_NAME.jpg"

const sharpen_image = await sharp("PATH/TO/IMAGE");
const image_meta = await sharpen_image.metadata();
const extension = get_file_extension(image_meta.format);
const file_name = name.replace(`.${extension}`, "");
await sharpen_image
  .resize(Math.round(image_meta.width * 0.5))
  .toFile(`PATH/TO/OUTPUT/${file_name}_half.${extension}`)

sharpにファイルを投入しリサイズした後、ファイル名の末尾に_halfの文字を追加して保存しています。(なんか、もっと良いやり方がある気もする…)

ここではconst nameという形で定数を代入していますが、実際にはfsなどの処理で動的に対象ファイルのファイル名を入れています。

画像の圧縮

縮小版ができたので、画像を圧縮しています。画像の圧縮には各種「imagemin」のプラグインを使っています。

const imagemin = require("imagemin-keep-folder");
const imageminMozjpeg = require("imagemin-mozjpeg");
const imageminPngquant = require("imagemin-pngquant");
const imageminGifsicle = require("imagemin-gifsicle");
const imageminSvgo = require("imagemin-svgo");

await imagemin(["PATH/TO/images/**/*.{jpg,png,gif,svg}"], {
  plugins: [
    imageminMozjpeg({ quality: 80 }),
    imageminPngquant({ quality: [0.95, 1] }),
    imageminGifsicle(),
    imageminSvgo()
  ]
});

ここでの圧縮は非可逆圧縮です。なので、元の画像からは劣化していますが、見た目には影響のないレベルのクオリティ設定にしています。体感的にはAdobe Illustratorで描きだした元画像の20~40%くらい削減される気がしてます。

この処理を経て、imagesフォルダ内の画像が圧縮されます。

処理をまとめる

const fs = require("fs-extra");
const path = require("path");
const resize = require("resize");
const image_compress = require("compress");

const src_image_path = path.resolve(__dirname, "PATH/TO/images_src");
const dist_image_path = path.resolve(__dirname, "PATH/TO/images");

await resize.exec();
await image_compress.exec();
await fs.copySync(src_image_path, dist_image_path);

上記のリサイズと圧縮の処理をexportして、コピーの処理と合体させて一つのjsにまとめました。package.jsonのnpm scriptsに以下を追加しておきます。

"scripts": {
  "image-optimize": "node image_optimize.js"
}

Netlifyデプロイ設定

Netlifyのデプロイ設定のBuild commandにyarn run image-optimize && yarn run generateを設定します(自分はパッケージマネージャーにyarnを使っているのでyarnコマンドですが、npmを使っている方はnpmを使ってください)

yarn run generateの方はNuxtのgenerateコマンドです。画像最適化したのちにgenerateして静的ファイルを生成しています。

これでNetlifyデプロイ時に画像最適化処理を自動でやってくれます。

さいごに

面倒くさい処理はどんどん機械にまかせてしまいましょう。

スポンサードリンク