如何在Node.js Express应用程序中呈现预编译的Jade(Pug)模板?

我有一个nodejs应用程序,使用Express和Jade(现在帕格)。 我想预编译玉石模板以获得更好的性能。 我已经能够使用jade --client将所有.jade文件转换为相应的.js。

如何在我的应用程序中使用这些js文件? 我没有很多nodejs / express的经验,但我认为它必须要求改变渲染引擎? 我已阅读官方文档,说使用runtime.js但我找不到任何文件,如何使用。

Jade(现在的Pug)是一个很棒的模板引擎,但是这些视图的编译却消耗了很多资源。 玉 。 当然,你可以使用生产中的“caching视图”特性来caching编译的视图,但是编译后的视图会存储在内存中 ,这会消耗很多资源。 感谢Jade,我开发的最新的快速应用程序在超过800毫秒的时间内响应了第一个请求,所以我不想改变模板引擎,就像你一样,我决定编译我的开发中的Jade视图环境并部署这些文件而不是原始视图。

为了使用由名为template的函数组成的.js文件的编译视图,您需要使用jade 运行时 。 运行时生成属性值,并执行其他的东西,如转义值。 template函数接受一个用于dynamic数据的参数。

由于这些函数是为客户端编译的,编译的视图依赖于全局的jade运行时(即window.jade )。 在node.js中,你可以填充GLOBAL对象,例如GLOBAL.jade = require('jade/lib/runtime')但这不是一个好主意。 我决定修改编译的函数,所以:

  1. 我们可以通过使用module.exportsrequire编译的视图( .js文件)。
  2. 该函数接受第二个参数,这是玉石运行时。

下面的代码片段使用.gulpfile中的.gulpfile gulp-jade.gulpfile gulp-replace节点模块:

 gulp.task('compile-jade', () => { // get all the jade files and compile them for client return gulp.src([ '../views/**/*.jade' ]).pipe(jade({ client: true })) // replace the function definition .pipe(replace('function template(locals)', 'module.exports = function(locals, jade)')) .pipe(gulp.dest('../views_js') ); }); 

现在我们已经改变了函数声明,我们可以加载编译后的文件( .js文件)而不是.jade文件。 但还有另一个问题。 没有预制的模板引擎(据我所知)使用这些文件。 所以我们需要定义一个新的引擎。 这很容易:

 let jade = require('jade/lib/runtime'); app.engine('js', function (filePath, options, callback) { // define the template engine let data = require(filePath)(options, jade); callback(null, data); }); 

现在我们可以在express中更改视图相关的设置:

 app.set('view engine', 'js'); app.set('views', path.join(__dirname, 'views_js')); 

现在响应第一个请求启动应用程序需要7ms的时间。 只要注意, require为不存在的文件引发错误,所以你可以考虑使用try/catch或承诺处理可能的exception。

你可以尝试使用非常简单的requirejs模块。 在你的服务器端代码中,你可以在一个文件夹中预先编译你的jade文件,然后在客户端,你可以调用require函数来运行你的预编译模板,如下所示:

 require(['<template_name>'], function (parse) { document.getElementById(<div_id).innerHTML = parse({ locals: <data_to_be_passed> }) }) 

你可以使用jade-runtime模块(非官方)。 当你require("jade-runtime") ,似乎添加一个“玉”对象的GLOBAL对象,所以它可能就这样工作。

对我来说有效的方法是将以下代码添加到包含(客户端模式)已编译模板函数的文件中。

 jade = require("jade-runtime").runtime module.exports = 

请参阅https://github.com/meryn/make-document-html及其Makefile以查看它的工作情况(编译后的,需要的模板函数以lib / template.js结尾)。 但是也可以在Node.js中完成。

编辑

我需要补充一点,除非你想阻止Jade的依赖(就像我做的那样),没有必要使用预编译的模板文件来获得预编译的好处。 您可以在某处执行templateFn = jade.compile(templateCode)并重新使用它。 事实上,如果express在res.render(templateName, vars)时不caching已编译模板本身,我会感到惊讶。 如果没有,这将是浪费的。 但是我没有快递的经验。 你有没有检查过什么快递渲染function呢?