106

Am I wrong in finding that Node.js does no gzip compression and there are no modules out there to perform gzip compression? How can anyone use a web server that has no compression? What am I missing here? Should I try to—gasp—port the algorithm to JavaScript for server-side use?

Simon East
  • 55,742
  • 17
  • 139
  • 133
SnickersAreMyFave
  • 5,047
  • 8
  • 26
  • 24

13 Answers13

82

Node v0.6.x has a stable zlib module in core now - there are some examples on how to use it server-side in the docs too.

An example (taken from the docs):

// 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);
hughsk
  • 3,822
  • 1
  • 21
  • 16
  • 1
    I ran into an issue with Internet Explorer not liking the zlib header which I resolved by using 'createDeflateRaw' instead of 'createDeflate' – mark Jan 10 '14 at 19:14
65

If you're using Express, then you can use its compress method as part of the configuration:

var express = require('express');
var app = express.createServer();
app.use(express.compress());

And you can find more on compress here: http://expressjs.com/api.html#compress

And if you're not using Express... Why not, man?! :)

NOTE: (thanks to @ankitjaininfo) This middleware should be one of the first you "use" to ensure all responses are compressed. Ensure that this is above your routes and static handler (eg. how I have it above).

NOTE: (thanks to @ciro-costa) Since express 4.0, the express.compress middleware is deprecated. It was inherited from connect 3.0 and express no longer includes connect 3.0. Check Express Compression for getting the middleware.

Milimetric
  • 13,411
  • 4
  • 44
  • 56
  • 3
    Down vote without a comment? Let me know why and hopefully I can improve the answer. Or feel free to edit yourself. – Milimetric Jan 12 '14 at 02:27
  • 3
    `This middleware should be placed "high" within the stack to ensure all responses may be compressed. ` Ensure that this is above your routes and static handler – ankitjaininfo Feb 12 '14 at 08:53
  • 18
    From now on `express.compress` middleware (which was inherited from connect 3.0<) is deprecated (since express 4.0) as it does not includes connect 3.0< anymore. Check https://github.com/expressjs/compression for getting the middleware. – Ciro Costa Mar 11 '14 at 01:31
  • 3
    to "Why not, man?!", the graphs on this page comparing raw http and express framework may give you a reason. express slows it down a bit https://raygun.io/blog/2015/02/node-js-performance-node-js-vs-io-js/ – ejfrancis Feb 23 '15 at 22:24
  • :) That was meant to be a bit tongue in cheek. I actually don't love express, there are many more things I wish it did and much more polish I wish it had. But it does well enough I suppose, until something else eclipses it. – Milimetric Feb 24 '15 at 03:06
48

1- Install compression

npm install compression

2- Use it

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

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

compression on Github

CoyBit
  • 1,592
  • 1
  • 17
  • 19
  • 2
    how to check whether static assest are gzip or not ! – Rizwan Patel Jun 08 '17 at 10:13
  • my images are not getting gzipped – Jeson Dias Jul 12 '17 at 06:49
  • actually you should this middleware when you are sending big JS/CSS files or big JSON files.. using this middleware won't give you benefit, instead it will consume more cpu resources. @JesonDias – gkd May 02 '18 at 11:01
  • @JesonDias you shouldn't gzip images because JPEG already includes a compression algo that works much better for images than gzip. gzip is more for text based stuff. – user3413723 Apr 25 '19 at 17:11
38

Generally speaking, for a production web application, you will want to put your node.js app behind a lightweight reverse proxy such as nginx or lighttpd. Among the many benefits of this setup, you can configure the reverse proxy to do http compression or even tls compression, without having to change your application source code.

yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • 1
    don't let node serve static files, let the proxy take care of compression, find it to be best practice in prod-env, you might want to use nginx or lighty anyway to avoid your root usr running node on port 80 – ezmilhouse Feb 14 '12 at 02:11
  • Depending on the usage, I'd really consider this to be the right answer. – prasanthv Mar 15 '16 at 18:11
  • @ezmilhouse Even if you have a proxy, your node.js server still has to *serve* those static files to the proxy, and there's no reason to waste bandwidth even in pipes inside the same machine. – B T Nov 22 '16 at 02:11
8

For compressing the file you can use below code

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.");

For decompressing the same file you can use below code

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.");
Krish Jackman
  • 101
  • 1
  • 3
  • Would love to see some descriptional text in this answer! While your code snippets may answer the question, it is good practice to include some explanations for the TO and the rest of the world to understand _why_ it answers the question. – Clijsters May 11 '17 at 11:44
8

Although you can gzip using a reverse proxy such as nginx, lighttpd or in varnish. It can be beneficial to have most http optimisations such as gzipping at the application level so that you can have a much granular approach on what asset's to gzip.

I have actually created my own gzip module for expressjs / connect called gzippo https://github.com/tomgco/gzippo although new it does do the job. Plus it uses node-compress instead of spawning the unix gzip command.

tomgco
  • 81
  • 1
  • 3
6

Even if you're not using express, you can still use their middleware. The compression module is what I'm using:

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)
B T
  • 57,525
  • 34
  • 189
  • 207
5

Use gzip compression

Gzip compressing can greatly decrease the size of the response body and hence increase the speed of a web app. Use the compression middleware for gzip compression in your Express app. For example:

var compression = require('compression');
var express = require('express')
var app = express()
app.use(compression())
Community
  • 1
  • 1
Jai dewani
  • 143
  • 1
  • 9
3

While as others have right pointed out using a front end webserver such as nginx can handle this implicitly, another option, is to use nodejitsu's excellent node-http-proxy to serve up your assets.

eg:

httpProxy.createServer(
 require('connect-gzip').gzip(),
 9000, 'localhost'
).listen(8000);

This example demonstrates support for gzip compression through the use of connect middleware module: connect-gzip.

cavalcade
  • 1,367
  • 14
  • 15
2

As of today, epxress.compress() seems to be doing a brilliant job of this.

In any express app just call this.use(express.compress());.

I'm running locomotive on top of express personally and this is working beautifully. I can't speak to any other libraries or frameworks built on top of express but as long as they honor full stack transparency you should be fine.

J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
Crispen Smith
  • 513
  • 4
  • 20
  • 2
    This doesn't really have any new information, it duplicates this answer: http://stackoverflow.com/a/14341423/1355166 – gcochard Mar 22 '13 at 21:38
2

How about this?

node-compress
A streaming compression / gzip module for node.js
To install, ensure that you have libz installed, and run:
node-waf configure
node-waf build
This will put the compress.node binary module in build/default.
...

Shay Erlichmen
  • 31,691
  • 7
  • 68
  • 87
2

There are multiple Gzip middlewares for Express, KOA and others. For example: https://www.npmjs.com/package/express-static-gzip

However, Node is awfully bad at doing CPU intensive tasks like gzipping, SSL termination, etc. Instead, use a ‘real’ middleware services like nginx or HAproxy, see bullet 3 here: http://goldbergyoni.com/checklist-best-practice-of-node-js-in-production/

Yonatan
  • 1,816
  • 1
  • 14
  • 7
1

It's been a few good days with node, and you're right to say that you can't create a webserver without gzip.

There are quite a lot options given on the modules page on the Node.js Wiki. I tried out most of them, but this is the one which I'm finally using -

https://github.com/donnerjack13589/node.gzip

v1.0 is also out and it has been quite stable so far.

Sudhanshu
  • 6,893
  • 3
  • 19
  • 10
  • I think your comment is a bit misleading. While gzip is common in modern web applications, it's not a *necessity*. I think it's perfectly fine and standards compliant to not use it. – Simon East Oct 10 '17 at 00:38