Node.JS: библиотека для модификации http ответов

от автора

Некоторое время назад писал сайт с бэкендом на Express/Node.JS. Возникла проблема с минификацией ответов. Нашел много готовых пакетов, но у всех была проблема — не минифицировался html после шаблонов. В итоге принял решение написать свой маленький и родной велосипед — библиотеку web-minify, позволяющую встроить хук перед отправкой клиенту и модифицировать ответ.

Установка пакета

npm i @dmitriym09/web-minify --save

Думаю, самое лучшее описание библиотеки для разработчика — пример кода=)

Пример

web-minify — middleware-функция:

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;     }   } ]));

В данном примере будут перехватываются все ответы с Content-Type, содержащие подстроку «css». Тело ответа обрабатывается с помощью csso, postcss, precss, autoprefixer. В параметре contentType передается String (будет искаться вхождение String.prototype.indexOf()) или RegExp (RegExp.prototype.test()). Параметр minify — функция Function(data:String, req:Request, res:Response), должна возвращать String с новым телом или Promise, который в свою очередь разрешается String. При неотловленом исключении клиент получит ответ 500.

Как уже сказал, большинство существующих популярных библиотек с похожим функционалом хорошо минифицирует статические файлы. Однако минификация сгенерированных в коде (например html шаблонизатором) ответов не работает. Одна из проблем — ответ может отправляться частями, а для обработки обычно нужны полные данные. Соответственно нужно перехватывать все отправки пользователю, собирать и уже в конце обрабатывать и отсылать. Это нужно учитывать при использовании web-minify: тот терабайтный файл, который вы хотите отправить клиенту и который попадает под contentType, накапливаться в памяти.

Примеры

Минификация HTML с помощью html-minifier из юнит-тестов

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(`<!DOCTYPE html> <html lang="en">  <head> <meta charset="utf-8">  </head>  <body> <h1>Test</h1>  <p>Test</p> </body>`); 	});   	request(app) 	  .get('/') 	  .set('Accept', 'text/html; charset=utf-8') 	  .expect('Content-Type', 'text/html; charset=utf-8') 	  .expect('<!doctype html><html lang=en><head><meta charset=utf-8></head><body><h1>Test</h1><p>Test</p></body></html>') 	  .expect(200) 	  .end(done) });

Модификации JSON и кода ответа с возвратом Promise из юнит-тестов

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 доступна на github и в npm под лицензией MIT.

Спасибо за внимание! Критика, предложения и комментарии приветствуются!


ссылка на оригинал статьи https://habr.com/post/425371/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *