nestjs sharp 压缩图片

479 阅读4分钟

引言

在现代网络应用中,优化图片是提高性能和用户体验的关键一环。Node.js 提供了多种库和工具来处理和压缩图片,本文将介绍几种主流的 Node.js 图片压缩库,并通过nestjs框架使用sharp 库以及如何使用它来实现不同的压缩方式。

1. 图片压缩的重要性

在 Web 开发中,图片是网站加载速度的重要因素之一。过大的图片文件会导致页面加载缓慢,影响用户体验和 SEO。因此,使用有效的图片压缩工具至关重要,不但可以简约存储空间还能提高用户访问的速度,降低宽度消耗

2. 主流图片压缩库比较

npmtrends.com对比了大家比较常用的npm压缩资源框架:canvas,imagemin,jimp,sharp

image.png

能看到sharp文档地址的下载是最大的,且优势有:

  • 性能优越: sharp 是基于 libvips 的图像处理库,性能出色,特别适合需要大规模图片处理的应用场景。
  • 功能丰富: 提供了各种图像处理功能,如大小调整、格式转换、滤镜应用等。
  • 简单易用: 提供了清晰的 API 和文档,方便开发者快速上手。

3. 使用 sharp 的简单示例

这里我们使用nestjs框架创建应用支持图片上传,在nestjs入门实战(二):上传图片代码基础上添加sharp对上传的图片进行压缩

最终压缩效果

sharp压缩质量75%情况下的效果:原图为左文件大小3.1MB,压缩图为右文件大小144kb 5.jpg

安装sharp依赖

由于sharp最新版本最node版本要求(^18.17.0 or >= 20.3.0),我的node版本<18.17.0,所以这里选择了指定的历史版本 v0.32.1

 npm i sharp@0.32.1 --save

创建压缩的图片位置

修改main.ts入口文件,压缩后的图片放入根目录下的uploads/compress

// main.ts

import { NestFactory } from '@nestjs/core';
import * as express from 'express';
import * as path from 'path';
import { existsSync, mkdirSync } from 'fs';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
+  const uploadDir = path.join(process.cwd(), 'uploads', 'compress');
  if (!existsSync(uploadDir)) {
    mkdirSync(uploadDir, { recursive: true });
  }

  app.use('/uploads', express.static(path.join(process.cwd(), 'uploads')));
  await app.listen(3000);
  
}
bootstrap();

创建压缩图片方法:compressImage

src/upload/upload.service.ts创建sharp相关的压缩图片代码,参数:压缩质量为quality:75尽量做到无损压缩,webp方式压缩图片

// src/upload/upload.service.ts

import { Injectable } from '@nestjs/common';
import * as sharp from 'sharp';
import * as fs from 'fs';
import * as path from 'path';

@Injectable()
export class UploadService {
    async compressImage(file: Express.Multer.File): Promise<string> {
        const outputDir = path.join(process.cwd(), 'uploads/compress');
        const fileName = file.filename;
        const filePath = path.join(outputDir, file.filename);
        const compressedImageBuffer = await sharp(file.path)
            .webp({ quality: 75 }) 
            .toBuffer();
            
        fs.writeFileSync(filePath, compressedImageBuffer);
        return fileName; 
    }
}

上传资源api添加压缩功能

upload.controller.ts中对上传图片进行压缩并返回压缩的图片和原图

// src/upload/upload.controller.ts

import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { UploadService } from './upload.service';

@Controller('upload')
export class UploadController {

    constructor(private readonly uploadService: UploadService) { }

    @Post('/uploadImage')
    @UseInterceptors(FileInterceptor('file', {
        limits: { fileSize: Math.pow(1024, 2) * 5 } // 限制图片上传最大5MB
    }))
    async uploadImage(@UploadedFile() file) {

        const fileName = await this.uploadService.compressImage(file);
        return {
            originImage: `http://localhost:3000/uploads/${fileName}`,
            compressImage: `http://localhost:3000/uploads/compress/${fileName}`
        };
    }

}

Postman 上传图片

Postman中选中需要上传的图片访问:localhost:3000/upload/uploadImage访问接口,服务返回原图地址和压缩图地址

image.png

压缩结果对比

上传的原图大小:3.1MB

image.png

压缩后的原图大小:144kb

image.png

原图与压缩图效果对比:

左边为原图效果,右边为压缩图效果

5.jpg

压缩策略

本文主要是以webp方式,压缩质量75%,实际开发中需要按照需求来配置压缩参数,一般的策略有:

  • 小图片 (< 10KB) :

    • 小体积的图片通常可以转换为 base64 编码直接嵌入到 HTML 或 CSS 中,减少 HTTP 请求次数,加快页面加载速度。适用于图标、小按钮等。
  • 中等大小图片 (10KB - 500KB) :

    • 对于中等大小的图片,推荐使用 WebP 格式进行压缩。WebP 格式可以显著减小文件大小,同时保持较高的视觉质量,适合用于网站的主要图片内容,如产品展示图、头图等。
  • 大图片 (> 500KB) :

    • 对于体积较大但不是特别重要的图片,可以考虑将图片质量降至 75 或更低的水平进行压缩,以减小文件大小,同时保持合理的视觉质量。这种策略适用于背景图、幻灯片等。
  • 重要性与质量平衡:

    • 对于重要且需要高质量展示的图片(如公司 logo、产品高清图片等),可以适度压缩以确保页面加载速度,但需要确保不影响视觉效果和用户体验。
  • 自动化处理:

    • 结合自动化工具和脚本,根据图片大小和类型自动选择合适的压缩策略。例如使用 Node.js 中的 sharp 或其他图片处理库,结合条件判断和批量处理功能来优化网站中的图片。

总结

在选择图片压缩工具时,需要根据项目需求和性能考量进行选择。sharp 提供了出色的性能和灵活的功能,是处理和压缩图片的理想选择。