lal*_*exa 3 imagemin npm-scripts
我正在尝试imagemin使用npm脚本创建脚本并使用imagemin-cli它.首先,我将文件复制到dist(或.tmp用于开发)文件夹,然后使用以下脚本压缩图像:
的package.json
...
scripts {
"copy:dev": "cpx app/src/**/*.{html,png,jpg,mp4,webm} .tmp/",
"copy:prod": "cpx app/src/**/*.{html,png,jpg,mp4,webm} dist/",
"imagemin:dev": "imagemin app/src/images/**/* -o .tmp/images/",
"imagemin:prod": "imagemin app/src/images/**/* -o dist/images/",
...
},
Run Code Online (Sandbox Code Playgroud)
因此,当我运行这些脚本时,压缩后所有图像都放在文件夹中images/.
有没有办法压缩图像并保持文件夹结构?也许与另一个插件或其他东西.
Gijs Rogé提出了一个未合并的(截至 2020 年 6 月中旬)拉取请求,可以在输出目录中保留目录结构。
您可以通过直接从 Github 安装、引用 repo 甚至特定提交来安装尚未在注册表中列出的 npm 模块:
npm install https://github.com/<username>/<repository>#<commit> --save-dev
要使用 Gijs Rogé 的修复程序安装 imagemin,请运行...
npm install https://github.com/imagemin/imagemin#bfd7c547045f68ed92243c6a772f6265a08a687f --save-dev
...并通过设置启用脚本中的新选项preserveDirectories: true:
// Note: imports and plugin configs have been omitted for brevity
const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
...
(async () => {
const files = await imagemin(['input_dir/**/*.{jpg,jpeg,png,svg}'], {
destination: 'output_dir/',
?preserveDirectories: true,
plugins: [
imageminMozjpeg( ... ),
imageminPngquant( ... ),
imageminSvgo( ... )
]
});
Run Code Online (Sandbox Code Playgroud)
在 中.jpg找到的Ainput_dir/some/sub/dir/image.jpg现在将被处理并写入output_dir/input_dir/some/sub/dir/image.jpg.
用于destination: '.'原地覆盖原始文件。
这是一种通过保持文件夹结构来压缩图像的方法吗?
简短的回答是不,不是 imagemin-cli
imagemin,(基于API imagemin-cli构建),不提供保留文件夹结构的机制.请参阅项目github repo中的open issue/feature-request #191.
实现您的要求的跨平台方法是编写一个自定义node.js实用程序脚本,该脚本直接使用imagemin API.如此有效......构建您自己的CLI工具,可以通过它运行npm-scripts.
以下要点展示了如何实现这一目标......
imagemin.js
实用程序节点脚本如下:
#!/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);
});
Run Code Online (Sandbox Code Playgroud)
注意: 上面的代码使用1.0.5的是imageminAPI 版本而不是最新版本 - 为什么?请参阅下面"附加说明"部分下的第1点.)
卸载并安装新软件包
imagemin-cli因为它不再需要:$ npm un -D imagemin-cli
1.0.5 npm$ npm i -D imagemin@1.0.5
$ 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",
...
},
...
Run Code Online (Sandbox Code Playgroud)
注意: 要使用上面显示的要点优化图像,不必使用原始帖子/问题中命名copy:prod和copy:dev显示的两个脚本)
glob \"app/src/...上面脚本的一部分使用cli-glob来匹配必要的图像源文件.
然后将路径传送到imagemin.js实用程序节点脚本.
当包含-v(详细)参数/标志时,每个处理过的图像都会记录到控制台.要省略日志记录,只需删除该-v标志即可.
的-o(输出)参数/标志用于指定目标文件夹名称.例如dist或.tmp.-o省略值for时,结果图像将输出到项目根目录.
补充说明:
使用imagemin版本1.0.5的原因是因为此API允许将src值指定为单个文件路径.在大于2.0.0API的版本中,src期望值为glob模式,如最新版本5.2.2所示.
上面列出的要点imagemin.js将保存到名称bin与其存在于同一文件夹中的文件夹中package.json.它可以通过在前面添加点[.]例如.scripts或者更改为首选名称或不可见文件夹.bin.无论您选择什么,您都需要相应地更新脚本的路径npm-scripts.