Node.jsとgulpを使っていい感じに画像を最適化する。
実際に使用した結果130MBくらいあったHexoで作ったイラストポートフォリオサイトが30MBまで減った。

必要なの

  • Node.js
  • npm
  • gulp
    • gulp-scale-images
    • flat-map
    • gulp-webp

手順

Node.jsとnpmのインストール方法は省略

gulp関連のインストール

npm install gulp gulp-webp@4.0.1 flat-map gulp-scale-images --save-dev

gulp-webp 5.x 以降はこの記事のスクリプトではうごきません

下記スクリプトを gulpfile.js としてプロジェクトのルートに配置

const path = require('path')
const gulp = require('gulp');
const webp = require('gulp-webp');
const scaleImages = require('gulp-scale-images')
const flatMap = require('flat-map').default

const webpPerFile = (file, cb) =>{
    const webpFile = file.clone()
    webpFile.scale = {maxWidth:1536, maxHeight:1536,format: 'webp',fit: 'inside'} // 大きさ定義。fitは変更しないことを推奨
    cb(null,[webpFile])
}

const computeFileName = (output, scale, cb) => {
	const fileName = [
		path.basename(output.path, output.extname), 
		scale.format || output.extname
	].join('.')
	cb(null, fileName)
}

function weboptimize () {
    return gulp.src('source/**/*.{jpg,jpeg,png}') // インプットパス
        .pipe(webp())
        .pipe(flatMap(webpPerFile))
        .pipe(scaleImages(computeFileName))
        .pipe(gulp.dest('source/')) // アウトプットパス
};

exports.webp = weboptimize

以下のコマンドを実行することでアウトプットする場所に小さくされたwebpが出力される

npx gulp webp

おまけ Hexoのmarkdown内の画像リンクをwebpに変換する

gulp-replaceをインストールする

npm install --save-dev gulp-replace

下記スクリプトをgulpfile.jsに追記とか保存とかする

const gulp = require('gulp');
const replace = require('gulp-replace');

function pnglinkweb (){
    return gulp.src('source/**/*.md') //インプットパス
        .pipe( replace(/(?<=\!\[.*\]*)(png|jpeg|jpg)/g,'webp') )
        .pipe( replace(/(?<=cover.*)(png|jpeg|jpg)/g,'webp') ) // HexoのCoverイメージリンク変換なのでいい感じに改変してください。
        .pipe(gulp.dest('source/')) // アウトプットパス
}

exports.webpreplace = pnglinkweb

以下のコマンドを実行することでmarkdownの画像リンクの拡張子がwebpになる

npx gulp webpreplace

まとめ

インストール

npm install --save-dev gulp gulp-webp flat-map gulp-scale-images gulp-replace

スクリプト

const path = require('path')
const gulp = require('gulp');
const webp = require('gulp-webp');
const scaleImages = require('gulp-scale-images')
const flatMap = require('flat-map').default
const replace = require('gulp-replace');

const webpPerFile = (file, cb) =>{
    const webpFile = file.clone()
    webpFile.scale = {maxWidth:1536, maxHeight:1536,format: 'webp',fit: 'inside'}
    cb(null,[webpFile])
}

const computeFileName = (output, scale, cb) => {
	const fileName = [
		path.basename(output.path, output.extname),
		scale.format || output.extname
	].join('.')
	cb(null, fileName)
}

function weboptimize () {
    return gulp.src('source/**/*.{jpg,jpeg,png}')
        .pipe(webp())
        .pipe(flatMap(webpPerFile))
        .pipe(scaleImages(computeFileName))
        .pipe(gulp.dest('source/'))
};

function pnglinkweb (){
    return gulp.src('source/**/*.md')
        .pipe( replace(/(?<=\!\[.*\]*)(png|jpeg|jpg)/g,'webp') )
        .pipe( replace(/(?<=cover.*)(png|jpeg|jpg)/g,'webp') ) // HexoのCoverイメージリンク変換なのでいい感じに改変してください。
        .pipe(gulp.dest('source/'))
}

exports.webp = weboptimize
exports.webpreplace = pnglinkweb

コマンド

npx gulp webpreplace
npx gulp webp

参考にしたサイト