这是一种在保持文件夹结构的情况下压缩图像的方法吗?
简短的回答是否定的,不是imagemin-cli
imagemin,(API imagemin-cli 是在此基础上构建的),不提供保留文件夹结构的机制。请参阅项目 github 存储库中的 open issue/feature-request #191。
解决方案
实现您的要求的跨平台方法是编写一个直接利用imagemin API 的自定义node.js 实用程序脚本。如此有效...构建您自己的 CLI 工具,可以通过 npm-scripts 运行。
以下要点展示了如何实现这一点...
imagemin.js
实用程序node脚本如下:
#!/usr/bin/env node
'use strict';
var path = require('path');
var readline = require('readline');
var Imagemin = require('imagemin');
var outdir = process.env.PWD; // Default output folder.
var verbose = false; // Default no logging.
// The folder name specified MUST exist in the `glob` pattern of the npm-script.
var DEST_SUBROOT_FOLDER = 'images';
// Nice ticks for logging aren't supported via cmd.exe
var ticksymbol = process.env.npm_config_shell.indexOf('bash') !== -1 ? '✔' : '√';
var rl = readline.createInterface({
input: process.stdin,
output: null,
terminal: false
});
// Handle the optional `-o` argument for the destination folder.
if (process.argv.indexOf('-o') !== -1) {
outdir = process.argv[process.argv.indexOf('-o') + 1];
}
// Handle the optional `-v` argument for verbose logging.
if (process.argv.indexOf('-v') !== -1) {
verbose = true;
}
/**
* Utilizes the Imagemin API to create a new instance for optimizing each image.
* @param {String} srcpath - The filepath of the source image to optimize.
* @param {String} destpath - The destination path to save the resultant file.
* @param {Function} - The relevent `use` plugin (jpegtran|optipng|gifsicle).
*/
function imagemin(srcpath, destpath, plugin) {
var im = new Imagemin()
.src(srcpath)
.dest(destpath)
.use(plugin);
im.optimize(function (err, file) {
if (err) {
console.error('Error: ' + err);
process.exit(1);
}
if (file && verbose) {
console.log('\x1b[32m%s\x1b[0m', ticksymbol, destpath);
}
});
}
/**
* Obtains the destination path and file suffix from the original source path.
* @param {String} srcpath - The filepath for the image to optimize.
* @return {{dest: String, type: String}} dest path and ext (.jpg|.png|.gif).
*/
function getPathInfo(srcpath) {
var ext = path.extname(srcpath),
parts = srcpath.split(path.sep),
subpath = parts.slice(parts.indexOf(DEST_SUBROOT_FOLDER), parts.length);
subpath.unshift(outdir);
return {
dest: path.normalize(subpath.join(path.sep)),
ext: ext
};
}
/**
* Triggers the relevent imagemin process according to file suffix (jpg|png|gif).
* @param {String} srcpath - The filepath of the image to optimize.
*/
function optimizeImage(srcpath) {
var p = getPathInfo(srcpath);
switch (p.ext) {
case '.jpg':
imagemin(srcpath, p.dest, Imagemin.jpegtran({ progressive: true }));
break;
case '.png':
imagemin(srcpath, p.dest, Imagemin.optipng({ optimizationLevel: 5 }));
break;
case '.gif':
imagemin(srcpath, p.dest, Imagemin.gifsicle({ interlaced: true }));
break;
}
}
// Read each line from process.stdin (i.e. the filepath)
rl.on('line', function(srcpath) {
optimizeImage(srcpath);
});
注意: 上面的代码使用了imagemin API 的1.0.5 版本,而不是最新版本 - 为什么?请参阅下面“附加说明”部分下的第 1 点。)
卸载和安装新软件包
- 首先卸载
imagemin-cli,因为它不再需要:
$ npm un -D imagemin-cli
- 下一次安装imagemin 版本
1.0.5 (这是一个较旧的软件包,所以npm 的安装时间可能比平时长)
$ npm i -D imagemin@1.0.5
- 然后安装cli-glob。这将用于指定 glob 模式以匹配图像以进行优化。
$ npm i -D cli-glob
npm 脚本
如下更新您的npm-scripts:
...
"scripts": {
"imagemin:prod": "glob \"app/src/images/**/*.{png,jpg,gif}\" | node bin/imagemin -v -o dist",
"imagemin:dev": "glob \"app/src/images/**/*.{png,jpg,gif}\" | node bin/imagemin -v -o .tmp",
...
},
...
注意: 要使用上面显示的要点优化图像,不必使用原始文件中显示的两个名为 copy:prod 和 copy:dev 的脚本帖子/问题)
-
上面脚本的glob \"app/src/... 部分使用cli-glob 来匹配必要的图像源文件。
-
然后将路径通过管道传送到 imagemin.js 实用程序节点脚本。
-
当包含-v(详细)参数/标志时,每个处理的图像都会记录到控制台。要省略日志记录,只需删除 -v 标志即可。
-
-o(输出)参数/标志用于指定目标文件夹名称。例如。 dist 或 .tmp。当-o 的值被省略时,生成的图像将输出到项目根目录。
补充说明:
-
之所以使用imagemin版本1.0.5是因为这个API
允许将 src 值指定为单个文件路径。在大于2.0.0 的版本中,API 期望src 值是一个全局模式,如最新版本5.2.2 中所示。
-
以上要点假设imagemin.js 被保存到名为bin 的文件夹中,该文件夹与package.json 存在于同一文件夹中。可以将其更改为首选名称,或通过在其前面加上点 [.] 来作为不可见文件夹,例如.scripts 或 .bin。无论您选择什么,都需要相应地更新 npm-scripts 中脚本的路径。