Node.js: minification on the fly considered harmful

Node.js: minification on the fly considered harmful

Minification on the fly is one of the available options in a Node.js application but it's not the best choice if we consider carefully the actual impact of our implementation.

Minification on the fly is one of the available options in a Node.js application but it's not the best choice if we consider carefully the actual impact of our implementation.

This feature is made up of two basic routines:

  1. creating the required Express routes for our assets
  2. minifying the assets and return the generated output in our routes.

We need two modules for our task:


npm install uglify-js --save
npm install uglifycss --save

Now we can create an helper class that makes use of the newly installed modules:


'use strict';

const path = require('path');
const abs = path.dirname(process.mainModule.filename);
const ugCSS = require('uglifycss');
const ugJS = require('uglify-js');

class Assets {
    constructor(path) {
        this.asset = abs + path;
    }
    _minifyCSS(file) {
        let output = ugCSS.processFiles([file]); // Add error handling
        return output;
    }

    _minifyJS(file) {
        let output = ugJS.minify(file); // Add error handling
        return output.code;
    }

    minify() {
        let self = this;
        return new Promise((resolve, reject) => {
            if(/\.css$/.test(self.asset)) {
                resolve(self._minifyCSS(self.asset));
            } else if(/\.js$/.test(self.asset)) {
              resolve(self._minifyJS(self.asset));  
            } else {
              reject('Not a valid file');
            }
        });
    }
}

module.exports = Assets;

The final step is to define our routes in Express:


'use strict';
const app = require('express')();
const Assets = require('./classes/Assets');

app.get('/assets/js/main.js', (req, res) => {
    let minifier = new Assets('/theme/js/main.js');
    minifier.minify().then(output => {
        res.set('Content-Type', 'text/javascript');
        res.send(output);
    }).catch(err => {
        // Add error handling
    });
});

app.get('/assets/css/main.css', (req, res) => {
    let minifier = new Assets('/theme/css/main.css');
    minifier.minify().then(output => {
        res.set('Content-Type', 'text/css');
        res.send(output);
    }).catch(err => {
        // Add error handling
    });
});

I do not recommend this technique on an heavy-load production site. The problem is that in each request there's a repeated access to the filesystem. This will sooner or later lead to high peaks of memory usage which is potentially harmful on the long run.