使用 Node.js 生成优化的图像格式
图像是任何 Web 应用程序的重要组成部分,但如果优化不当,它们也可能成为性能问题的主要根源。在本文中,我们将介绍如何使用 Node.js
自动生成优化的图像格式,并以最适合用户浏览器的格式显示它们。
配置
首先我们需要一个为我们处理图像处理的库,而Sharp就是本文将使用的图像处理库。Sharp
是一个用于图像处理和操作的高性能 Node.js
库。它的设计速度快、内存效率高,非常适合处理大图像和生成多种图像格式。
安装:
npm i sharp
图像生成脚本
优化网络图像的第一步是为每个图像生成多种格式,每种格式都有自己的优点和缺点。某些格式(例如 JPEG
)适合具有多种颜色的复杂图像,而其他格式(例如 WebP
)更适合具有较少颜色的简单图像。具体的图片格式分析请看前端图片格式这篇文章。
要生成不同的图像格式,我们可以使用 Node.js
和 Sharp
图像处理库。下面是一个示例脚本,它为图像文件夹中的每个图像生成 avif
和 webp
格式:
const sharp = require('sharp');
const fs = require('fs');const inputFolder = 'images';
const outputFolder = 'output';const formats = ['avif', 'webp'];if (!fs.existsSync(outputFolder)) {fs.mkdirSync(outputFolder);
}fs.readdir(inputFolder, (err, files) => {if (err) {console.error(err);return;}files.forEach(file => {if (file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.png')) {const inputPath = `${inputFolder}/${file}`;const name = file.substring(0, file.lastIndexOf('.'));formats.forEach(format => {const outputPath = `${outputFolder}/${name}.${format}`;if (!fs.existsSync(outputPath)) {sharp(inputPath).toFormat(format, { quality: 80 }).toFile(outputPath, (err) => {if (err) {console.error(err);} else {console.log(`${name}.${format} saved`);}});}});}});
});
代码说明
const sharp = require('sharp');
const fs = require('fs');const inputFolder = 'images';
const outputFolder = 'output';const formats = ['avif', 'webp'];
在这几行代码中,导入sharp
和fs
库,将输入文件夹设置为images
,将输出文件夹设置为output
,并将要生成的格式定义为avif
和webp
。
if (!fs.existsSync(outputFolder)) {fs.mkdirSync(outputFolder);
}
在这里,代码检查是否存在输出文件夹outputFolder
,如果不存在,则使用 fs.mkdirSync()
方法来创建它。这可确保在生成任何图像之前输出文件夹存在。
fs.readdir(inputFolder, (err, files) => {if (err) {console.error(err);return;}
})
使用fs.readdir
方法来判断输入文件夹是否存在。
files.forEach(file => {if (file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.png')) {//...}
})
这段代码使用forEach
方法遍历输入文件夹中的所有文件。如果文件名以.jpg
、.jpeg
、 或.png
结尾,则继续生成相应的avif
和webp
文件。
const inputPath = `${inputFolder}/${file}`;
const name = file.substring(0, file.lastIndexOf('.'));
这里,将输入文件路径定义为inputPath
,并提取不带扩展名的文件名作为输出文件名。
formats.forEach(format => {const outputPath = `${outputFolder}/${name}.${format}`;if (!fs.existsSync(outputPath)) {sharp(inputPath).toFormat(format, { quality: 80 }).toFile(outputPath, (err) => {if (err) {console.error(err);} else {console.log(`${name}.${format} saved`);}});}
});
在这里,脚本使用formats.forEach()
循环遍历每种格式(即avif
和webp
)。对于每种格式,它将输出文件路径定义为outputPath
如果输出文件不存在,则使用 Sharp
的toFormat()
函数以指定格式生成相应的图像,质量为 80。然后使用toFile()
保存输出文件,并向控制台记录一条消息,指示文件已保存。
在浏览器中显示优化的图像
一旦我们为每个输入图像生成了多种优化的图像格式,我们就可以在应用程序中显示它们。为此,我们可以使用 HTML
中的<picture>
和<source>
元素来指定不同格式的不同图像源。下面是一个以最适合用户浏览器的格式显示图像的例子:
<picture><source srcSet="./output/1.avif" type="image/avif" /><source srcSet="./output/1.webp" type="image/webp" /><img src="./images/1.png" />
</picture>
img
它将用作不支持avif
或webp
的浏览器的后备显示图像。
在浏览器的请求:
可以看到浏览器使用webp
的方式展示图片。
结论
网站上的图像加载速度可能很慢,并且在不同设备上看起来并不总是很好。重要的是要让它们加载得更快、看起来更好,这样人们才能更喜欢我们的网站。在本文中我们学习了如何使用 Sharp
和 HTML
中的<picture>
,<source>
制作同一图像的不同版本,并为每种设备显示最佳版本。通过这样做,我们的网站对于每个使用它的人来说将会更快、看起来更好!