简体   繁体   中英

How do I play nice with Node.js Express compress middleware?

I want to use some middleware to trim all whitespace between HTML tags and collapse all other whitespace to a single space. This is to aid with CSS because white-space-collapse: discard; isn't widely available (if at all?) and I'm not a fan of other workarounds . I'm fine with a naive approach for now -- but I do want it to play nice with the express.compress middleware.

This is what I have:

module.exports = function trimmer() {
    function getSize(chunk) {
        return Buffer.isBuffer(chunk)
        ? chunk.length
        : Buffer.byteLength(chunk);
    }

    return function trimmer(req, res, next) {
        var end = res.end
            , write = res.write
            , isHtml
        ;

        res.on('header', function() {
            //res.removeHeader('Content-Length'); // another thing I've tried; don't entirely understand it though
        });

        res.write = function(chunk, encoding) {
            var type = res.getHeader('Content-Type') || '';
            isHtml = type.indexOf('text/html') >= 0;
            if (!isHtml) {
                write.apply(res, arguments);
                return;
            }

            var html = chunk
                .toString(encoding)
                .replace(/>\s+</g, '><')
                .replace(/\s{2,}/g, ' ')
            ;

            var buffer = new Buffer(html, encoding);

            try {
                res.setHeader('Content-Length', getSize(buffer));
            } catch (ex) {}
            return write.call(res, buffer, encoding);
        };

        next();
    };
};

This works perfectly fine like so:

app.configure(function() {
    app.use(trimmer());
    // app.use(express.compress()); // till I uncomment this line... then it breaks
    app.use(express.favicon());
    app.use('/images',  express.static(images));
    app.use('/scripts', express.static(scripts));
    app.use(less({ src: pub, dest: tmp }));
    app.use(express.static(tmp));
    app.use(express.static(views));
});

Uncommenting the noted line above causes exceptions related to not being able to modify headers that've already been sent. That's fair, I understand that. I looked at compress 's source code and it was a little above my head. What do I have to do/monkeypatch to not step on compress 's toes (and vice-versa)?

Have you tried putting app.use(trimmer()); below app.use(express.compress()); ? The way it's currently written, trimmer will be called after the response is compressed; switching the order ensures that (1) you're not trying to trim compressed data, and (2) the results of your trimming will be properly compressed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM