Skip to content

Instantly share code, notes, and snippets.

@developit
Last active April 13, 2021 22:50
Show Gist options
  • Save developit/1cc31d2ce6f3374e2d21941f27788ecc to your computer and use it in GitHub Desktop.
Save developit/1cc31d2ce6f3374e2d21941f27788ecc to your computer and use it in GitHub Desktop.

Revisions

  1. developit revised this gist Aug 26, 2020. 1 changed file with 20 additions and 15 deletions.
    35 changes: 20 additions & 15 deletions polkompress.js
    Original file line number Diff line number Diff line change
    @@ -24,15 +24,17 @@ export default function compress({ threshold = 1024, level = -1, brotli = false,

    /** @type {zlib.Gzip | zlib.BrotliCompress} */
    let compress;
    let pendingHead;
    let pendingStatus;
    let started = false;
    let size = 0;

    function start() {
    started = true;
    // @ts-ignore
    size = res.getHeader('Content-Length') | 0 || size;
    if (mimes.test(res.getHeader('Content-Type') + '') && size >= threshold) {
    const compressible = mimes.test(res.getHeader('Content-Type') + '');
    const cleartext = !res.getHeader('Content-Encoding');
    if (compressible && cleartext && size >= threshold) {
    res.setHeader('Content-Encoding', encoding);
    res.removeHeader('Content-Length');
    if (encoding === 'br') {
    @@ -49,18 +51,20 @@ export default function compress({ threshold = 1024, level = -1, brotli = false,
    on.call(res, 'drain', () => compress.resume());
    compress.on('end', () => end.call(res));
    // const start = Date.now();
    // compress.on('end', () => console.log(`${encoding};q=${level};dur=${Date.now() - start}`));
    // compress.on('end', () => {
    // console.log(`${req.url}[${(size / 1000) | 0}kb]: ${encoding};dur=${Date.now() - start}`);
    // });
    }
    // pendingListeners.forEach(p => on.apply(res, p));
    writeHead.apply(res, pendingHead);
    pendingListeners.forEach(p => on.apply(res, p));
    if (pendingStatus) writeHead.call(res, pendingStatus);
    }

    const { end, write, on, writeHead } = res;

    res.writeHead = function (status, reason, headers) {
    if (typeof reason !== 'string') [headers, reason] = [reason, headers];
    if (headers) for (let i in headers) res.setHeader(i, headers[i]);
    pendingHead = [status];
    pendingStatus = status;
    return this;
    };
    res.write = function (chunk, enc) {
    @@ -70,19 +74,20 @@ export default function compress({ threshold = 1024, level = -1, brotli = false,
    return compress.write(chunk, enc);
    };
    res.end = function (chunk, enc) {
    if (!compress) return end.call(this, chunk, enc);
    size += getChunkSize(chunk, enc);
    if (!started) start();
    if (!compress) return end.call(this, chunk, enc);
    return compress.end(chunk, enc);
    };
    /** Not currently used. */
    // let pendingListeners = [];
    // res.on = function (type, listener) {
    // if (!pendingListeners) on.call(this, type, listener);
    // else if (compress) compress.on(type, listener);
    // else pendingListeners.push([type, listener]);
    // return this;
    // };
    let pendingListeners = [];
    res.on = function (type, listener) {
    if (!pendingListeners) on.call(this, type, listener);
    else if (compress) compress.on(type, listener);
    else pendingListeners.push([type, listener]);
    return this;
    };

    next();
    };
    }
    }
  2. developit created this gist May 23, 2020.
    3 changes: 3 additions & 0 deletions *polkompress.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    # Polkompress

    A tiny zero-dependency compression middleware for [polka](https://npm.im/polka) (& express!) with native Brotli support.
    12 changes: 12 additions & 0 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    {
    "name": "polkompress",
    "main": "polkompress.cjs",
    "module": "polkompress.js",
    "type": "module",
    "exports": {
    "import": "polkompress.js",
    "default": "polkompress.cjs"
    },
    "scripts": { "prepare":"cjyes", "prepack":"mv *polkompress.md README.md", "postpack": "mv README.md *polkompress.md" },
    "devDependencies": { "cjyes":"0.3.1" }
    }
    88 changes: 88 additions & 0 deletions polkompress.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    import zlib from 'zlib';

    function getChunkSize(chunk, enc) {
    if (!chunk) return 0;
    if (Buffer.isBuffer(chunk)) return Buffer.byteLength(chunk, enc);
    return chunk.length;
    }

    const noop = () => {};

    const MIMES = /text|javascript|xml/i;

    /** @returns {import('polka').Middleware} */
    export default function compress({ threshold = 1024, level = -1, brotli = false, gzip = true, mimes = MIMES } = {}) {
    const brotliOpts = (typeof brotli === 'object' && brotli) || {};
    const gzipOpts = (typeof gzip === 'object' && gzip) || {};

    return (req, res, next = noop) => {
    const accept = req.headers['accept-encoding'] + '';
    const encoding = ((brotli && accept.match(/\bbr\b/)) || (gzip && accept.match(/\bgzip\b/)) || [])[0];

    // skip if no response body or no supported encoding:
    if (req.method === 'HEAD' || !encoding) return next();

    /** @type {zlib.Gzip | zlib.BrotliCompress} */
    let compress;
    let pendingHead;
    let started = false;
    let size = 0;

    function start() {
    started = true;
    // @ts-ignore
    size = res.getHeader('Content-Length') | 0 || size;
    if (mimes.test(res.getHeader('Content-Type') + '') && size >= threshold) {
    res.setHeader('Content-Encoding', encoding);
    res.removeHeader('Content-Length');
    if (encoding === 'br') {
    const params = {
    [zlib.constants.BROTLI_PARAM_QUALITY]: level,
    [zlib.constants.BROTLI_PARAM_SIZE_HINT]: size
    };
    compress = zlib.createBrotliCompress({ params: Object.assign(params, brotliOpts) });
    } else {
    compress = zlib.createGzip(Object.assign({ level }, gzipOpts));
    }
    // backpressure
    compress.on('data', chunk => write.call(res, chunk) === false && compress.pause());
    on.call(res, 'drain', () => compress.resume());
    compress.on('end', () => end.call(res));
    // const start = Date.now();
    // compress.on('end', () => console.log(`${encoding};q=${level};dur=${Date.now() - start}`));
    }
    // pendingListeners.forEach(p => on.apply(res, p));
    writeHead.apply(res, pendingHead);
    }

    const { end, write, on, writeHead } = res;

    res.writeHead = function (status, reason, headers) {
    if (typeof reason !== 'string') [headers, reason] = [reason, headers];
    if (headers) for (let i in headers) res.setHeader(i, headers[i]);
    pendingHead = [status];
    return this;
    };
    res.write = function (chunk, enc) {
    size += getChunkSize(chunk, enc);
    if (!started) start();
    if (!compress) return write.call(this, chunk, enc);
    return compress.write(chunk, enc);
    };
    res.end = function (chunk, enc) {
    if (!compress) return end.call(this, chunk, enc);
    size += getChunkSize(chunk, enc);
    return compress.end(chunk, enc);
    };
    /** Not currently used. */
    // let pendingListeners = [];
    // res.on = function (type, listener) {
    // if (!pendingListeners) on.call(this, type, listener);
    // else if (compress) compress.on(type, listener);
    // else pendingListeners.push([type, listener]);
    // return this;
    // };

    next();
    };
    }