如何通过Node.js实践实现高效的内容压缩技术?

2026-03-31 13:591阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2343个文字,预计阅读时间需要10分钟。

如何通过Node.js实践实现高效的内容压缩技术?

利用Node.js实现内容压缩(gzip/br/deflate)的方法如下,以下文章将带大家通过实践了解Node.js如何实现内容压缩:

在Node.js中,实现内容压缩主要有两种方式:使用内置的`zlib`模块和第三方库。以下是具体方法,希望对大家有所帮助!

1. 使用zlib模块

Node.js内置了`zlib`模块,可以方便地实现gzip、br和deflate压缩。

javascriptconst http=require('http');const zlib=require('zlib');

const server=http.createServer((req, res)=> { const data='这里是需要压缩的内容'; zlib.gzip(data, (err, buffer)=> { if (err) { console.error(err); return; } res.setHeader('Content-Encoding', 'gzip'); res.end(buffer); });});

server.listen(3000, ()=> { console.log('Server running on http://localhost:3000');});

2. 使用第三方库

除了zlib模块,还可以使用第三方库如`compression`来实现内容压缩。

javascriptconst http=require('http');const compression=require('compression');

const server=http.createServer((req, res)=> { res.setHeader('Content-Encoding', 'gzip'); res.end('这里是需要压缩的内容');});

server.listen(3000, ()=> { console.log('Server running on http://localhost:3000');});

在查看应用日志时,发现进入日志页面后,总是提示“总是要登录。以下是解决方法:

1. 检查登录逻辑是否正确,确保用户在登录后能正确获取到登录状态。

2. 检查前端代码,确保在发送请求时携带了正确的登录凭证。

3. 检查后端代码,确保在处理登录请求时返回了正确的登录状态。

希望以上内容能对大家有所帮助!”

利用Nodejs怎么实现内容压缩?下面本篇文章给大家通过实践来聊聊Node侧实现内容压缩(gzip/br/deflate)的方法,希望对大家有所帮助!

如何通过Node.js实践实现高效的内容压缩技术?

在查看自己的应用日志时,发现进入日志页面后总是要几秒钟才会加载(接口没做分页),于是打开网络面板查看

这才发现接口返回的数据都没有被压缩,本以为接口用Nginx反向代理了,Nginx会自动帮我做这一层(这块后面探究一下,理论上是可行的)

这里的后端是 Node 服务

本文就分享一下 HTTP数据压缩相关知识以及在Node侧的实践

前置知识

下面的客户端均指浏览器

accept-encoding

客户端在向服务端发起请求时,会在请求头(request header)中添加accept-encoding字段,其值标明客户端支持的压缩内容编码格式

content-encoding

服务端在对返回内容执行压缩后,通过在响应头(response header)中添加content-encoding,来告诉浏览器内容实际压缩使用的编码算法

deflate/gzip/br

deflate是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。

gzip 是基于 DEFLATE 的算法

br指代Brotli,该数据格式旨在进一步提高压缩比,对文本的压缩相对deflate能增加20%的压缩密度,而其压缩与解压缩速度则大致不变

zlib模块

Node.js包含一个zlib 模块,提供了使用 GzipDeflate/Inflate、以及 Brotli 实现的压缩功能

这里以gzip为例分场景列举多种使用方式,Deflate/InflateBrotli使用方式一样,只是API不一样

基于stream的操作

基于buffer的操作

引入几个所需的模块

const zlib = require('zlib') const fs = require('fs') const stream = require('stream') const testFile = 'tests/origin.log' const targetFile = `${testFile}.gz` const decodeFile = `${testFile}.un.gz`文件的解/压缩

解/压缩结果查看,这里使用du指令直接统计解压缩前后结果

# 执行 du -ah tests # 结果如下 108K tests/origin.log.gz 2.2M tests/origin.log 2.2M tests/origin.log.un.gz 4.6M tests基于流(stream)的操作

使用createGzipcreateUnzip

  • 注:所有 zlib API,除了那些显式同步的 API,都使用 Node.js 内部线程池,可以看做是异步的
  • 因此下面的示例中的压缩和解压代码应分开执行,否则会报错

方式1: 直接利用实例上的pipe方法传递流

// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) readStream.pipe(zlib.createGzip()).pipe(writeStream) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) readStream.pipe(zlib.createUnzip()).pipe(writeStream)

方式2: 利用stream上的pipeline,可在回掉中单独做其它的处理

// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) stream.pipeline(readStream, zlib.createGzip(), writeStream, err => { if (err) { console.error(err); } }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) stream.pipeline(readStream, zlib.createUnzip(), writeStream, err => { if (err) { console.error(err); } })

方式3: Promise化pipeline方法

const { promisify } = require('util') const pipeline = promisify(stream.pipeline) // 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) pipeline(readStream, zlib.createGzip(), writeStream) .catch(err => { console.error(err); }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) pipeline(readStream, zlib.createUnzip(), writeStream) .catch(err => { console.error(err); })基于Buffer的操作

利用 gzipunzip API,这两个方法包含同步异步类型

  • 压缩
    • gzip
    • gzipSync
  • 解压
    • unzip
    • unzipSync

方式1:readStreamBuffer,然后进行进一步操作

  • gzip:异步

// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { zlib.gzip(Buffer.concat(buff), targetFile, (err, resBuff) => { if(err){ console.error(err); process.exit() } fs.writeFileSync(targetFile,resBuff) }) })

  • gzipSync:同步

// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { fs.writeFileSync(targetFile,zlib.gzipSync(Buffer.concat(buff))) })

方式2: 直接通过readFileSync读取

// 压缩 const readBuffer = fs.readFileSync(testFile) const decodeBuffer = zlib.gzipSync(readBuffer) fs.writeFileSync(targetFile,decodeBuffer) // 解压 const readBuffer = fs.readFileSync(targetFile) const decodeBuffer = zlib.gzipSync(decodeFile) fs.writeFileSync(targetFile,decodeBuffer)文本内容的解/压缩

除了对文件压缩,有时候也许要对传输的内容进行直接进行解压缩

这里以压缩文本内容为例

// 测试数据 const testData = fs.readFileSync(testFile, { encoding: 'utf-8' })基于流(stream)操作

这块就考虑 string => buffer => stream的转换就行

string => buffer

const buffer = Buffer.from(testData)

buffer => stream

const transformStream = new stream.PassThrough() transformStream.write(buffer) // or const transformStream = new stream.Duplex() transformStream.push(Buffer.from(testData)) transformStream.push(null)

这里以写入到文件示例,当然也可以写到其它的流里,如HTTP的Response(后面会单独介绍)

transformStream .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(targetFile))基于Buffer操作

同样利用Buffer.from将字符串转buffer

const buffer = Buffer.from(testData)

然后直接使用同步API进行转换,这里result就是压缩后的内容

const result = zlib.gzipSync(buffer)

可以写入文件,在HTTP Server中也可直接对压缩后的内容进行返回

fs.writeFileSync(targetFile, result)Node Server中的实践

这里直接使用Node中 http 模块创建一个简单的 Server 进行演示

在其他的 Node Web 框架中,处理思路类似,当然一般也有现成的插件,一键接入

const http = require('http') const { PassThrough, pipeline } = require('stream') const zlib = require('zlib') // 测试数据 const testTxt = '测试数据123'.repeat(1000) const app = http.createServer((req, res) => { const { url } = req // 读取支持的压缩算法 const acceptEncoding = req.headers['accept-encoding'].match(/(br|deflate|gzip)/g) // 默认响应的数据类型 res.setHeader('Content-Type', 'application/json; charset=utf-8') // 几个示例的路由 const routes = [ ['/gzip', () => { if (acceptEncoding.includes('gzip')) { res.setHeader('content-encoding', 'gzip') // 使用同步API直接压缩文本内容 res.end(zlib.gzipSync(Buffer.from(testTxt))) return } res.end(testTxt) }], ['/deflate', () => { if (acceptEncoding.includes('deflate')) { res.setHeader('content-encoding', 'deflate') // 基于流的单次操作 const originStream = new PassThrough() originStream.write(Buffer.from(testTxt)) originStream.pipe(zlib.createDeflate()).pipe(res) originStream.end() return } res.end(testTxt) }], ['/br', () => { if (acceptEncoding.includes('br')) { res.setHeader('content-encoding', 'br') res.setHeader('Content-Type', 'text/html; charset=utf-8') // 基于流的多次写操作 const originStream = new PassThrough() pipeline(originStream, zlib.createBrotliCompress(), res, (err) => { if (err) { console.error(err); } }) originStream.write(Buffer.from('<h1>BrotliCompress</h1>')) originStream.write(Buffer.from('<h2>测试数据</h2>')) originStream.write(Buffer.from(testTxt)) originStream.end() return } res.end(testTxt) }] ] const route = routes.find(v => url.startsWith(v[0])) if (route) { route[1]() return } // 兜底 res.setHeader('Content-Type', 'text/html; charset=utf-8') res.end(`<h1>404: ${url}</h1> <h2>已注册路由</h2> <ul> ${routes.map(r => `<li><a href="${r[0]}">${r[0]}</a></li>`).join('')} </ul> `) res.end() }) app.listen(3000)

更多node相关知识,请访问:nodejs 教程!

本文共计2343个文字,预计阅读时间需要10分钟。

如何通过Node.js实践实现高效的内容压缩技术?

利用Node.js实现内容压缩(gzip/br/deflate)的方法如下,以下文章将带大家通过实践了解Node.js如何实现内容压缩:

在Node.js中,实现内容压缩主要有两种方式:使用内置的`zlib`模块和第三方库。以下是具体方法,希望对大家有所帮助!

1. 使用zlib模块

Node.js内置了`zlib`模块,可以方便地实现gzip、br和deflate压缩。

javascriptconst http=require('http');const zlib=require('zlib');

const server=http.createServer((req, res)=> { const data='这里是需要压缩的内容'; zlib.gzip(data, (err, buffer)=> { if (err) { console.error(err); return; } res.setHeader('Content-Encoding', 'gzip'); res.end(buffer); });});

server.listen(3000, ()=> { console.log('Server running on http://localhost:3000');});

2. 使用第三方库

除了zlib模块,还可以使用第三方库如`compression`来实现内容压缩。

javascriptconst http=require('http');const compression=require('compression');

const server=http.createServer((req, res)=> { res.setHeader('Content-Encoding', 'gzip'); res.end('这里是需要压缩的内容');});

server.listen(3000, ()=> { console.log('Server running on http://localhost:3000');});

在查看应用日志时,发现进入日志页面后,总是提示“总是要登录。以下是解决方法:

1. 检查登录逻辑是否正确,确保用户在登录后能正确获取到登录状态。

2. 检查前端代码,确保在发送请求时携带了正确的登录凭证。

3. 检查后端代码,确保在处理登录请求时返回了正确的登录状态。

希望以上内容能对大家有所帮助!”

利用Nodejs怎么实现内容压缩?下面本篇文章给大家通过实践来聊聊Node侧实现内容压缩(gzip/br/deflate)的方法,希望对大家有所帮助!

如何通过Node.js实践实现高效的内容压缩技术?

在查看自己的应用日志时,发现进入日志页面后总是要几秒钟才会加载(接口没做分页),于是打开网络面板查看

这才发现接口返回的数据都没有被压缩,本以为接口用Nginx反向代理了,Nginx会自动帮我做这一层(这块后面探究一下,理论上是可行的)

这里的后端是 Node 服务

本文就分享一下 HTTP数据压缩相关知识以及在Node侧的实践

前置知识

下面的客户端均指浏览器

accept-encoding

客户端在向服务端发起请求时,会在请求头(request header)中添加accept-encoding字段,其值标明客户端支持的压缩内容编码格式

content-encoding

服务端在对返回内容执行压缩后,通过在响应头(response header)中添加content-encoding,来告诉浏览器内容实际压缩使用的编码算法

deflate/gzip/br

deflate是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。

gzip 是基于 DEFLATE 的算法

br指代Brotli,该数据格式旨在进一步提高压缩比,对文本的压缩相对deflate能增加20%的压缩密度,而其压缩与解压缩速度则大致不变

zlib模块

Node.js包含一个zlib 模块,提供了使用 GzipDeflate/Inflate、以及 Brotli 实现的压缩功能

这里以gzip为例分场景列举多种使用方式,Deflate/InflateBrotli使用方式一样,只是API不一样

基于stream的操作

基于buffer的操作

引入几个所需的模块

const zlib = require('zlib') const fs = require('fs') const stream = require('stream') const testFile = 'tests/origin.log' const targetFile = `${testFile}.gz` const decodeFile = `${testFile}.un.gz`文件的解/压缩

解/压缩结果查看,这里使用du指令直接统计解压缩前后结果

# 执行 du -ah tests # 结果如下 108K tests/origin.log.gz 2.2M tests/origin.log 2.2M tests/origin.log.un.gz 4.6M tests基于流(stream)的操作

使用createGzipcreateUnzip

  • 注:所有 zlib API,除了那些显式同步的 API,都使用 Node.js 内部线程池,可以看做是异步的
  • 因此下面的示例中的压缩和解压代码应分开执行,否则会报错

方式1: 直接利用实例上的pipe方法传递流

// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) readStream.pipe(zlib.createGzip()).pipe(writeStream) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) readStream.pipe(zlib.createUnzip()).pipe(writeStream)

方式2: 利用stream上的pipeline,可在回掉中单独做其它的处理

// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) stream.pipeline(readStream, zlib.createGzip(), writeStream, err => { if (err) { console.error(err); } }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) stream.pipeline(readStream, zlib.createUnzip(), writeStream, err => { if (err) { console.error(err); } })

方式3: Promise化pipeline方法

const { promisify } = require('util') const pipeline = promisify(stream.pipeline) // 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) pipeline(readStream, zlib.createGzip(), writeStream) .catch(err => { console.error(err); }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) pipeline(readStream, zlib.createUnzip(), writeStream) .catch(err => { console.error(err); })基于Buffer的操作

利用 gzipunzip API,这两个方法包含同步异步类型

  • 压缩
    • gzip
    • gzipSync
  • 解压
    • unzip
    • unzipSync

方式1:readStreamBuffer,然后进行进一步操作

  • gzip:异步

// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { zlib.gzip(Buffer.concat(buff), targetFile, (err, resBuff) => { if(err){ console.error(err); process.exit() } fs.writeFileSync(targetFile,resBuff) }) })

  • gzipSync:同步

// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { fs.writeFileSync(targetFile,zlib.gzipSync(Buffer.concat(buff))) })

方式2: 直接通过readFileSync读取

// 压缩 const readBuffer = fs.readFileSync(testFile) const decodeBuffer = zlib.gzipSync(readBuffer) fs.writeFileSync(targetFile,decodeBuffer) // 解压 const readBuffer = fs.readFileSync(targetFile) const decodeBuffer = zlib.gzipSync(decodeFile) fs.writeFileSync(targetFile,decodeBuffer)文本内容的解/压缩

除了对文件压缩,有时候也许要对传输的内容进行直接进行解压缩

这里以压缩文本内容为例

// 测试数据 const testData = fs.readFileSync(testFile, { encoding: 'utf-8' })基于流(stream)操作

这块就考虑 string => buffer => stream的转换就行

string => buffer

const buffer = Buffer.from(testData)

buffer => stream

const transformStream = new stream.PassThrough() transformStream.write(buffer) // or const transformStream = new stream.Duplex() transformStream.push(Buffer.from(testData)) transformStream.push(null)

这里以写入到文件示例,当然也可以写到其它的流里,如HTTP的Response(后面会单独介绍)

transformStream .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(targetFile))基于Buffer操作

同样利用Buffer.from将字符串转buffer

const buffer = Buffer.from(testData)

然后直接使用同步API进行转换,这里result就是压缩后的内容

const result = zlib.gzipSync(buffer)

可以写入文件,在HTTP Server中也可直接对压缩后的内容进行返回

fs.writeFileSync(targetFile, result)Node Server中的实践

这里直接使用Node中 http 模块创建一个简单的 Server 进行演示

在其他的 Node Web 框架中,处理思路类似,当然一般也有现成的插件,一键接入

const http = require('http') const { PassThrough, pipeline } = require('stream') const zlib = require('zlib') // 测试数据 const testTxt = '测试数据123'.repeat(1000) const app = http.createServer((req, res) => { const { url } = req // 读取支持的压缩算法 const acceptEncoding = req.headers['accept-encoding'].match(/(br|deflate|gzip)/g) // 默认响应的数据类型 res.setHeader('Content-Type', 'application/json; charset=utf-8') // 几个示例的路由 const routes = [ ['/gzip', () => { if (acceptEncoding.includes('gzip')) { res.setHeader('content-encoding', 'gzip') // 使用同步API直接压缩文本内容 res.end(zlib.gzipSync(Buffer.from(testTxt))) return } res.end(testTxt) }], ['/deflate', () => { if (acceptEncoding.includes('deflate')) { res.setHeader('content-encoding', 'deflate') // 基于流的单次操作 const originStream = new PassThrough() originStream.write(Buffer.from(testTxt)) originStream.pipe(zlib.createDeflate()).pipe(res) originStream.end() return } res.end(testTxt) }], ['/br', () => { if (acceptEncoding.includes('br')) { res.setHeader('content-encoding', 'br') res.setHeader('Content-Type', 'text/html; charset=utf-8') // 基于流的多次写操作 const originStream = new PassThrough() pipeline(originStream, zlib.createBrotliCompress(), res, (err) => { if (err) { console.error(err); } }) originStream.write(Buffer.from('<h1>BrotliCompress</h1>')) originStream.write(Buffer.from('<h2>测试数据</h2>')) originStream.write(Buffer.from(testTxt)) originStream.end() return } res.end(testTxt) }] ] const route = routes.find(v => url.startsWith(v[0])) if (route) { route[1]() return } // 兜底 res.setHeader('Content-Type', 'text/html; charset=utf-8') res.end(`<h1>404: ${url}</h1> <h2>已注册路由</h2> <ul> ${routes.map(r => `<li><a href="${r[0]}">${r[0]}</a></li>`).join('')} </ul> `) res.end() }) app.listen(3000)

更多node相关知识,请访问:nodejs 教程!