使用Node.js在生产模式下压缩脚本/CSS

11

我有一个运行在Node上的Web应用程序。目前所有(客户端)Javascript/CSS文件都没有被压缩以便于调试。

当我进入生产环境时,我希望压缩这些脚本。最好能像这样:

node app.js -production

如何在不更改HTML文件中的脚本标签的情况下提供已压缩的脚本版本?应该有类似这样的东西:如果我处于生产环境,则使用这两个已压缩(合并)的脚本,否则使用所有未压缩的脚本...

这可能吗?也许我想得太复杂了?

5个回答

21
您可能对Piler感兴趣。它是一个Node.js模块,当处于调试模式时,会像往常一样提供您指定的所有JavaScript(和CSS)文件,但在生产模式下进行了合并和压缩。
作为一项特殊功能,“CSS实时更新”(Piler中称为)可以通过Socket.io以实时方式强制进行CSS更新,以在浏览器中显示这些更新,这非常棒 :-)
技巧在于,在模板中您只有 script 和 link 元素占位符,Piler在运行时呈现这些元素-在调试模式下作为单个元素,在生产模式下作为动态生成的单个元素。
这样,您就可以忘记手动创建拼接和压缩版本的资产或使用构建工具,它就在运行时存在,但在开发和调试时始终拥有分离的完整版本。

5

您可以将静态文件放置在两个不同的位置。

以下是一些 Express 代码:

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

并使用以下命令启动节点

MODE=production node app.js

此外,如果您不想复制所有文件,您可以利用Express静态路由器在第一个文件时停止的事实,改为使用以下方法:
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

然而,对于压缩或未压缩的代码使用相同的名称会导致浏览器缓存问题。


@Pascal,快问一下 - 你是在建议将压缩后的js文件放在那个文件夹中吗?如果是这样,每次有更改时都必须在您的系统上构建它,然后使用git等推送到生产环境,这似乎不是一个很好的主意。 - tusharmath
不应该将压缩文件存储在git中。可以在生产服务器上使用服务器本身或类似于“grunt”的工具来生成压缩版本。 - Pascal Belloncle
要在生产模式下启动,请使用以下命令:NODE_ENV=production node app.js - DB Prasad

1

我想与大家分享我的最终解决方案。

我使用JSHTML for Express(链接描述在此输入)

在我的主节点文件中,我使用了一个特殊的路由:

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("/");
    }
});

正如您所见,我从config.getResourceBundle获取我的资源。这是一个简单的函数:
exports.getResourceBundle = function(identifier){
    switch(enviroment){
        case "development":
            return devConfig.getResourceBundle(identifier);
        case "production":
            return prodConfig.getResourceBundle(identifier);
        default:
            return devConfig.getResourceBundle(identifier);
    }
}

最后,这里有一个关于资产文件集合的示例:

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"
        ]
    }
(...)

我有2个文件夹。dev / prod。grunt将把压缩后的文件复制到prod /..并从dev /..中删除文件... 如果NODE_ENV变量设置为production,我将发送我的脚本/ css的压缩版本。 我认为这是目前最优雅的解决方案。


1

0

另一个与Node.js相关的模块是connect-cachify

它似乎不会为您实际进行缩小,但它确实允许您在生产中提供缩小版本,或在开发中提供所有原始脚本,而无需更改模板(感谢cachify_jscachify_css)。

看起来它的功能不如Piler丰富,但可能更简单,并且应该满足问题中提到的所有要求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接