gulp
+ imagemin-pngquant
で特定の画像を処理すると、大量の文字化けが流れて最終的にエラーが発生する現象に遭遇したのでメモ。
現象再現
現象再現のため、最小限構成を作りました。
{
"name": "pngquant_test",
"version": "1.0.0",
"description": "pngquant9.0.0のテストです",
"main": "gulpfile.js",
"scripts": {
"start": "gulp"
},
"author": "アルム=バンド",
"dependencies": {
"gulp": "^4.0.2",
"gulp-imagemin": "^7.1.0",
"imagemin-pngquant": "^9.0.0",
"imagemin": "^7.0.1"
}
}
package.json
はこのような形。検証のため、 gulp すら使わないパターンも考慮してプレーンの imagemin
も入れています。
const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
const imageminPng = require('imagemin-pngquant');
//画像圧縮
const imageminify = () => {
return gulp.src('src/**/*.png', {
since: gulp.lastRun(imageminify)
})
.pipe(imagemin([
imageminPng({
quality: [0.8, 0.9],
speed: 1
})
]))
.pipe(gulp.dest('dist/'));
};
//コールタスク
exports.default = gulp.parallel(imageminify);
gulpfile.js
。 src
ディレクトリの画像を dist
に出力するだけの簡単なタスクです。パラメータとしては quality
と speed
を指定。
const imagemin = require('imagemin');
const imageminPngquant = require('imagemin-pngquant');
(async () => {
await imagemin(['src/**/*.png'], {
destination: 'dist/',
plugins: [
imageminPngquant({
quality: [0.8, 0.9],
speed: 1
})
]
});
console.log('Images optimized');
})();
index.js
。 gulp 不使用のプレーンなもので、 imagemin-pngquant – npm のサンプルをコピーして上と同じパラメータを指定しただけです。
現象
これで以下の画像を処理します。
で、結果が以下。
gulp
> gulp
## 文字化け部分大量
stderr:
failed: true
timedOut: false
isCanceled: false
killed: false
fileName: PATH\TO\PROJECT\src\hoge.png
domainEmitter: [object Object]
domainThrown: false
[XX:XX:XX] 'default' errored after 28 s
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
gulp タスクの方は大量の文字化け文字が流れて、 ctrl
+ c
の強制終了もしばらく効かない(応答なし)になるというハングっぷり。
しばらく待って止まると、最後に上述のエラーが表示されます。
nodeスクリプト
> node ./index.js
(node:2344) UnhandledPromiseRejectionWarning: Error
at makeError (PATH\TO\PROJECT\node_modules\imagemin-pngquant\node_modules\execa\lib\error.js:59:11)
at handlePromise (PATH\TO\PROJECT\node_modules\imagemin-pngquant\node_modules\execa\index.js:114:26)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async PATH\TO\PROJECT\node_modules\p-pipe\index.js:12:19
at async handleFile (PATH\TO\PROJECT\node_modules\imagemin\index.js:21:9)
at async PATH\TO\PROJECT\node_modules\imagemin\index.js:54:13
at async Promise.all (index 0)
at async PATH\TO\PROJECT\index.js:5:5
(node:2344) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing
inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:2344) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
index.js
の方はまだ有情で、さっと止まってくれます。
検証
現象についていくつか検証しました。
- 他のpng画像で実験したところ、発生するもの(例: 上述サンプル)と発生しないものがあった
quality
のパラメータを[0.8, 0.9]
から[0.7, 0.9]
に変更すると正常に処理が完了したimagemin-pngquant
のバージョンを9.0.0
ではなく8.0.0
で同じ gulp タスクを走らせてもエラーにはならない
以上より、 imagemin-pngquant
のバージョン・圧縮率・画像の相性のような気はします。
各ツールのバージョン
Node.js
> node -v
v12.17.0
npm
>npm -v
6.14.4
yarn
>yarn -v
1.22.4
windows-build-tools
> npm list -g --depth 0
C:\Program Files (x86)\Nodist\bin
## 略
+-- windows-build-tools@1.3.2
## 略
Python
3.7.1150.0 (32bit)
対処療法
パッケージのバージョンを落とすのはやや気が引けたので、今回はquality
のパラメータを [0.8, 0.9]
から [0.7, 0.9]
に変更することで対処しました。
備考
npm や yarn でグローバルインストールしているパッケージとバージョンの一覧表示方法について。
npm
npm の場合は npm list -g --depth 0
yarn
yarn の場合は yarn global list