Node.js:Gzip压缩?

108

我是否错了,发现Node.js没有gzip压缩功能,也没有可以用于执行gzip压缩的模块?怎么会有人使用没有压缩功能的Web服务器呢?我错过了什么?我应该尝试将该算法传输到JavaScript以供服务器端使用吗?

13个回答

84

现在Node v0.6.x的核心中有一个稳定的zlib模块 - 文档中也有一些关于如何在服务器端使用它的示例。

以下是文档中的示例:

// server example
// Running a gzip operation on every request is quite expensive.
// It would be much more efficient to cache the compressed buffer.
var zlib = require('zlib');
var http = require('http');
var fs = require('fs');
http.createServer(function(request, response) {
  var raw = fs.createReadStream('index.html');
  var acceptEncoding = request.headers['accept-encoding'];
  if (!acceptEncoding) {
    acceptEncoding = '';
  }

  // Note: this is not a conformant accept-encoding parser.
  // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
  if (acceptEncoding.match(/\bdeflate\b/)) {
    response.writeHead(200, { 'content-encoding': 'deflate' });
    raw.pipe(zlib.createDeflate()).pipe(response);
  } else if (acceptEncoding.match(/\bgzip\b/)) {
    response.writeHead(200, { 'content-encoding': 'gzip' });
    raw.pipe(zlib.createGzip()).pipe(response);
  } else {
    response.writeHead(200, {});
    raw.pipe(response);
  }
}).listen(1337);

1
我遇到了一个问题,因为Internet Explorer不喜欢zlib标头,我用'createDeflateRaw'代替'createDeflate'解决了这个问题。 - mark

65
如果你正在使用Express,那么你可以在配置中使用它的压缩方法:
var express = require('express');
var app = express.createServer();
app.use(express.compress());

在这里您可以找到更多有关压缩的信息:http://expressjs.com/api.html#compress

如果您没有使用Express ……那为什么呢,伙计?! :)

注意:(感谢@ankitjaininfo)此中间件应该是您“使用”的第一个,以确保所有响应都已被压缩。确保它在路由和静态处理程序之上(例如,像我上面那样)。

注意:(感谢@ciro-costa)自 express 4.0 版本以来,express.compress 中间件已弃用。它是从 connect 3.0 继承而来的,而 express 不再包含 connect 3.0。请查看Express Compression以获取该中间件。


3
没有留下评论就点踩?请告诉我原因,我会尽力改善答案。或者你也可以随意编辑。 - Milimetric
3
这个中间件应该被放在“高”的位置上,以确保所有响应都可以被压缩。请确保它在路由和静态处理程序之上。 - ankitjaininfo
18
从现在开始,express.compress 中间件(继承自 connect 3.0<)已经被废弃(自 express 4.0 起),因为它不再包含 connect 3.0<。请查看 https://github.com/expressjs/compression 获取该中间件。 - Ciro Costa
3
“为什么不呢?!”如果你看一下这个页面上比较原始的http和express框架的图表,你可能会找到一个理由。Express会稍微使其变慢一些。链接是:https://raygun.io/blog/2015/02/node-js-performance-node-js-vs-io-js/ - ejfrancis
这是有点儿玩笑的。实际上我并不喜欢 Express,我希望它能做更多的事情,也希望它更加完善。但我想它还可以胜任,直到有其他更好的东西出现。 - Milimetric

48

1- 安装 压缩

npm install compression

2- 使用它

var express     = require('express')
var compression = require('compression')

var app = express()
app.use(compression())

压缩在Github上的页面


2
如何检查静态资源是否已经压缩为gzip格式! - Rizwan Patel
我的图片没有被压缩成gzip格式。 - Jeson Dias
实际上,当您发送大型JS / CSS文件或大型JSON文件时,应使用此中间件。使用此中间件不会给您带来好处,相反,它会消耗更多的CPU资源。@JesonDias - gkd
@JesonDias 你不应该使用gzip来压缩图片,因为JPEG已经包含了一种比gzip更适合图片的压缩算法。gzip更适用于文本内容。 - user3413723

38

一般而言,对于生产级 Web 应用程序,您应该将 Node.js 应用程序放在类似 nginx 或 lighttpd 的轻量级反向代理后面。这种设置的许多好处之一是,您可以配置反向代理进行 HTTP 压缩甚至 TLS 压缩,而无需更改应用程序源代码。


1
不要让Node服务静态文件,让代理处理压缩,这在生产环境中是最佳实践。你可能想使用Nginx或Lighty来避免在端口80上运行Node的根用户。 - ezmilhouse
根据使用情况,我真的认为这是正确的答案。 - prasanthv
即使您有代理,您的 Node.js 服务器仍然必须向代理“提供”这些静态文件,同样,在同一台机器内部的管道中浪费带宽是没有道理的。 - B T

10

你可以使用以下代码来压缩文件

var fs = require("fs");
var zlib = require('zlib');
fs.createReadStream('input.txt').pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log("File Compressed.");

为了解压相同的文件,您可以使用以下代码。
var fs = require("fs");
var zlib = require('zlib');
fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'));
console.log("File Decompressed.");

非常希望在回答中能够看到一些描述性的文字!虽然你的代码片段可能已经解答了问题,但是为了让提问者和其他人理解这个答案“为什么”有效,最好还是加入一些解释。 - Clijsters

8
虽然你可以使用反向代理(如nginx、lighttpd或varnish)进行gzip,但在应用程序级别进行大多数http优化(如gzip),可以更加细致地确定需要gzip的资源。我实际上为expressjs/connect创建了自己的gzip模块,称为gzippohttps://github.com/tomgco/gzippo,虽然它是新的,但确实起到了作用。此外,它使用node-compress而不是生成unix gzip命令。

3
我现在在一个小的 Node.js Web 服务器上使用 gzippo,效果很好! - bosgood
1
如何检查静态资产是否应用了Gzip? - Rizwan Patel

6

即使您没有使用express,仍然可以使用他们的中间件。我正在使用compression模块

var http = require('http')
var fs = require('fs')
var compress = require("compression")
http.createServer(function(request, response) {
  var noop = function(){}, useDefaultOptions = {}
  compress(useDefaultOptions)(request,response,noop) // mutates the response object

  response.writeHead(200)
  fs.createReadStream('index.html').pipe(response)
}).listen(1337)

5

使用gzip压缩

使用gzip压缩可以大幅减小响应体大小,从而提高Web应用程序的速度。在Express应用程序中使用压缩中间件进行gzip压缩。例如:

var compression = require('compression');
var express = require('express')
var app = express()
app.use(compression())

我们需要在客户端解压响应大小吗? - Siddharth Sunchu
1
@SiddharthSunchu 不,它是透明处理的。 - Gerhard Powell

3
虽然其他人已经正确指出使用前端Web服务器,例如nginx可以隐式地处理此问题,但另一种选择是使用nodejitsu的优秀node-http-proxy来提供您的资产。
例如:
httpProxy.createServer(
 require('connect-gzip').gzip(),
 9000, 'localhost'
).listen(8000);

这个例子展示了通过 connect middleware 模块支持gzip压缩的方法:connect-gzip

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接