Node.JS: library for modifying http responses
Some time ago I wrote a site with a backend on Express /Node.JS. There was a problem with the minimization of answers. I found many ready-made packages, but everyone had a problem - html after templates was not minified. As a result, I decided to write my own small and native bicycle - the web-minify library , which allows you to embed a hook before sending it to the client and modify the response.
I think the best description of a library for a developer is code example =)
web-minify - middleware function:
In this example, all responses with Content-Type containing the substring “css” will be intercepted. The response body is processed using csso , postcss , precss , autoprefixer . String is passed in the contentType parameter (the occurrence of String.prototype.indexOf () will be searched for or RegExp (RegExp.prototype.test ()). The minify parameter - Function (data: String, req: Request, res: Response) function, should return a String with a new body or Promise, which in turn is resolved by String. In case of non-catching exception, the client will receive a response of 500
As already said, most of the existing popular libraries with similar functionality well minify static files. However, the minification of the responses generated in the code (for example, html by the template engine) does not work. One of the problems is that the answer can be sent in parts, and for processing usually complete data is needed. Accordingly, you need to intercept all sending to the user, collect it and process and send it at the end. This should be taken into account when using web-minify : the terabyte file that you want to send to the client and which falls under contentType accumulates in memory.
Web-minify is available on github and in npm under the MIT license.
Thanks for attention! Criticism, suggestions and comments are welcome!
Package installation
npm i @dmitriym09/web-minify --save
I think the best description of a library for a developer is code example =)
Example
web-minify - middleware function:
const htmlminify = require('html-minifier').minify;
const csso = require('csso').minify;
const postcss = require('postcss');
const precss = require('precss');
const autoprefixer = require('autoprefixer');
const minify = require('web-minify');
app.use(minify([
{
contentType: /css/,
minify: async (data, req, res) => {
let resData = (await postcss([precss, autoprefixer]).process(data, { from: undefined })).css;
resData = csso(resData).css;
return resData;
}
}
]));
In this example, all responses with Content-Type containing the substring “css” will be intercepted. The response body is processed using csso , postcss , precss , autoprefixer . String is passed in the contentType parameter (the occurrence of String.prototype.indexOf () will be searched for or RegExp (RegExp.prototype.test ()). The minify parameter - Function (data: String, req: Request, res: Response) function, should return a String with a new body or Promise, which in turn is resolved by String. In case of non-catching exception, the client will receive a response of 500
As already said, most of the existing popular libraries with similar functionality well minify static files. However, the minification of the responses generated in the code (for example, html by the template engine) does not work. One of the problems is that the answer can be sent in parts, and for processing usually complete data is needed. Accordingly, you need to intercept all sending to the user, collect it and process and send it at the end. This should be taken into account when using web-minify : the terabyte file that you want to send to the client and which falls under contentType accumulates in memory.
Examples
HTML minification using html-minifier from unit tests
const htmlminify = require('html-minifier').minify;
it('HTML', (done) => {
const app = createServer([minify([
{
contentType: 'html',
minify: (data) => {
let res = htmlminify(data, {
removeAttributeQuotes: true,
collapseWhitespace: true,
conservativeCollapse: false,
decodeEntities: true,
keepClosingSlash: false,
preserveLineBreaks: false,
preventAttributesEscapin,
processConditionalComments: true,
removeAttributeQuotes: true,
removeComments: true,
trimCustomFragments: true,
useShortDoctype: true
});
return res;
}
}
])], function(req, res) {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end(`
Test
Test
`);
});
request(app)
.get('/')
.set('Accept', 'text/html; charset=utf-8')
.expect('Content-Type', 'text/html; charset=utf-8')
.expect('Test
Test
')
.expect(200)
.end(done)
});
Modifications to JSON and the Promise return code from unit tests
it('JSON', (done) => {
const app = createServer([minify([
{
contentType: /json/,
minify: (data, req, res) => {
return new Promise(function(resolve, reject) {
try {
res.statusCode = 456;
let o = JSON.parse(data);
o.dt = new Date('2018-09-28T11:05:13.492Z')
resolve(JSON.stringify(o))
}
catch(exc) {
reject(exc)
}
})
}
}
])], function(req, res) {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.end(JSON.stringify({a: 12}));
});
request(app)
.get('/')
.set('Accept', 'applicatio3n/json; charset=utf-8')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect('{"a":12,"dt":"2018-09-28T11:05:13.492Z"}')
.expect(456)
.end(done)
});
Web-minify is available on github and in npm under the MIT license.
Thanks for attention! Criticism, suggestions and comments are welcome!