使用Express合并、压缩和提供JavaScript文件,但响应未经过gzip压缩处理。

6

我正在使用Express构建一个Web应用程序。我想合并、压缩和提供.js文件。我编写了一个中间件,这是我的代码:

var fs = require('fs'),
    path = require('path'),
    uglify = require('uglify-js'),
    cache = '',
    scriptsDir = path.join(__dirname, '../scripts'),
    files = fs.readdirSync(scriptsDir);

// Sync read is not a problem since the following code is executed on startup
files.forEach(function(fname) {
    if (/^.*\.js$/.test(fname)) {
        cache += fs.readFileSync(path.join(scriptsDir, fname), 'utf8').toString();
    }
});
cache = uglify.minify(cache, { fromString: true }).code;

module.exports = function(req, res, next) {
    if (req.url === '/js/all.js')
        res.end(cache);
    else
        next();
};

中间件使用方法如下:
app.use(compress());
[...]
app.use(app.router);
app.use(jsMerger); // Here is my middleware
app.use(express.static(path.join(__dirname, '../public')));

问题在于响应未压缩。此外,响应中没有“标题”(我的意思是,没有缓存标题、ETag;使用 static 中间件提供的其他资源具有这些标题)。以下是响应内容:

X-Powered-By: Express
Transfer-Encoding: chunked
Date: Wed, 12 Mar 2014 14:04:19 GMT
Connection: keep-alive

我有点不明白,如何压缩响应呢?

为了进一步参考,行uglify = require('uglify-js')导入了uglify.js2库(https://github.com/mishoo/UglifyJS2)。 - mneri
1个回答

2
在添加了res.set('Content-Type', 'text/javascript')这行代码后,Express会对响应进行gzip压缩。完整代码如下:
module.exports = function(req, res, next) {
    if (req.url === '/js/all.js') {
        res.set('Content-Type', 'text/javascript');
        res.end(cache);
    } else {
        next();
    }
};

现在响应的头部如下:

X-Powered-By: Express
Vary: Accept-Encoding
Transfer-Encoding: chunked
Date: Wed, 12 Mar 2014 14:45:45 GMT
Content-Type: text/javascript
Content-Encoding: gzip
Connection: keep-alive

这是由于“compress”中间件的设计原因。你可以向“compress”提供一个“filter”选项:
app.use(express.compress({
    filter : function(req, res) {
        return /json|text|javascript/.test(res.getHeader('Content-Type'));
    }
});

压缩仅应用于与过滤器匹配的请求。默认过滤器为:

function(req, res){
    return /json|text|javascript|dart|image\/svg\+xml|application\/x-font-ttf|application\/vnd\.ms-opentype|application\/vnd\.ms-fontobject/.test(res.getHeader('Content-Type'));
};

如果您没有提供Content-Type头,请求将无法通过过滤器,express也无法对响应进行gzip压缩。

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