最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Minify ScriptsCSS in production mode with node.js - Stack Overflow

programmeradmin1浏览0评论

I have a web app that runs in node. All the (client) Javascript/CSS files are not minified at the moment to make it easier to debug.

When I am going into production, I would like to minify these scripts. It would be nice to have something like:

node app.js -production

How do I serve the minified version of my scripts without changing the script tags in my html files? There should be something like: if I am in production, use these 2 minified(combined) scripts, else use all my unminified scripts..

Is this possible? Maybe I am thinking too complicated?

I have a web app that runs in node. All the (client) Javascript/CSS files are not minified at the moment to make it easier to debug.

When I am going into production, I would like to minify these scripts. It would be nice to have something like:

node app.js -production

How do I serve the minified version of my scripts without changing the script tags in my html files? There should be something like: if I am in production, use these 2 minified(combined) scripts, else use all my unminified scripts..

Is this possible? Maybe I am thinking too complicated?

Share Improve this question edited Feb 12, 2013 at 20:45 Mechlar 4,97414 gold badges60 silver badges83 bronze badges asked Feb 12, 2013 at 20:35 ChristianChristian 7,42912 gold badges57 silver badges90 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 21

You might be interested in Piler. It's a Node.js module that delivers all the JavaScript (and CSS) files you specify as usual when in debug mode, but concatenated and minified when in production mode.

As a special feature, you can force CSS updates via Socket.io in real-time to appear in your browser (called "CSS Live Updated" in Piler), which is quite awesome :-).

The trick is that inside your template you only have placeholders for the script and link elements, and Piler renders these elements at runtime - as single elements in debug mode, and as a dynamically generated single element in production mode.

This way you can forget about creating concatenated and minified versions of your assets manually or using a build tool, it's just there at runtime, but you always have the separated, full versions when developing and debugging.

you could use 2 separate locations for your static files

Here's some express code:

if (process.env.MODE === "production") {
  app.use(express['static'](__dirname + '/min'));
} else {
  app.use(express['static'](__dirname + '/normal'));
}

and start node with

MODE=production node app.js

Furthermore, if you don't want to duplicate all your files, you could take advantage of the fact that express static router stops at the first file, and do something like this instead:

if (process.env.MODE === "production") {
  app.use(express['static'](__dirname + '/min'));  // if minized version exists, serves it
}
app.use(express['static'](__dirname + '/normal'));  // fallback to regular files

Using the same name for minimized or not is going to cause problem with browser caching, though.

I want to share my final solution with you guys.

I use JSHTML for Express (enter link description here)

In my main node file I use a special route:

app.get('/**:type(html)', function (req, res, next) {
var renderingUrl = req.url.substring(1, req.url.lastIndexOf("."));
//TODO: Find a better solution
    try{
        var assetUrl = req.url.substring(req.url.lastIndexOf("/") + 1, req.url.lastIndexOf("."));
        var assets = config.getResourceBundle(assetUrl);
        assets.production = config.getEnviroment() === "production";
        res.locals(assets);
        res.render(renderingUrl);
    }catch(e){
        res.redirect("/");
    }
});

As you can see, I get my assets from config.getResourceBundle. This is a simply function:

exports.getResourceBundle = function(identifier){
    switch(enviroment){
        case "development":
            return devConfig.getResourceBundle(identifier);
        case "production":
            return prodConfig.getResourceBundle(identifier);
        default:
            return devConfig.getResourceBundle(identifier);
    }
}

And finally an example for an asset file collection is here:

exports.getResourceBundle = function (identifier) {
    return resourceBundle[identifier];
};


resourceBundle = {
    index:{
        cssFiles:[
            "resources/dev/css/login.css",
            "resources/dev/css/logonDlg.css",
            "resources/dev/css/footer.css"
        ],
        jsFiles:[
            "resources/dev/js/lib/jquery/jquery.183.js",
            "resources/dev/js/utilities.js",
            "resources/dev/js/lib/crypto.3.1.2.js"
        ]
    },
    register:{
        cssFiles:[
            "resources/dev/css/login.css",
            "resources/dev/css/modalDialog.css",
            "resources/dev/css/footer.css"
        ],
        jsFiles:[
            "resources/dev/js/lib/jquery/jquery.183.js",
            "resources/dev/js/utilities.js",
            "resources/dev/js/lib/crypto.3.1.2.js",
            "resources/dev/js/lib/jquery.simplemodal.js",
            "resources/dev/js/xfiles.register.js"
        ]
    }
(...)

I have 2 folders. dev / prod. grunt will copy the minified files into prod/.. and deletes the files from dev/... And if the NODE_ENV variable is set to production, I will ship the minified versions of my scripts/css. I think this is the most elegant solution at the moment.

There are build tool plugins for you, may help you gracefully solve this problem:

For Gulp: https://www.npmjs.org/package/gulp-useref/

For Grunt: https://github.com/pajtai/grunt-useref

Another Node.js module which could be relevant is connect-cachify.

It doesn't seem to do the actual minification for you, but it does let you serve the minified version in production, or all the original scripts in development, without changing the templates (thanks to cachify_js and cachify_css).

Seems it's not as feature-rich as Piler, but probably a bit simpler, and should meet all the requirements mentioned in the question.

发布评论

评论列表(0)

  1. 暂无评论