简体   繁体   English

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

[英]How to render precompiled Jade (Pug) templates in a Node.js Express app?

I have a nodejs app that uses Express and Jade(now Pug). 我有一个使用Express和Jade(现在是Pug)的nodejs应用程序。 I want to precompile the jade templates for better performance. 我想预编译jade模板以获得更好的性能。 I have been able to convert the jade to javascript using jade --client to compile all the .jade files to corresponding .js. 我已经能够使用jade --client将jade转换为javascript以将所有.jade文件编译为相应的.js。

How do I use these js files in my app? 如何在我的应用程序中使用这些js文件? I don't have much experience with nodejs/express, but I think it must require changing the rendering engine? 我对nodejs / express没有太多经验,但我认为它必须要求更改渲染引擎? I have read the official documentation that says to use runtime.js but I couldn't find any documentation as how exactly it is to be used. 我已经阅读了使用runtime.js的官方文档,但我找不到任何文档,因为它是如何使用的。

Jade (now Pug) is a great templating engine, but the compilation of the views consume so much resources. Jade(现在的Pug)是一个很棒的模板引擎,但是视图的编译消耗了大量的资源。 Jade is slow . 玉很 Of course you can use the "cache view" feature of express on production that caches the compiled views, but the compiled views are stored in memory that can consume so much resources. 当然,您可以使用快速生成的“缓存视图”功能来缓存已编译的视图,但编译的视图存储可能占用大量资源的内存中。 Thanks to Jade, the latest express app that I had developed responded to the first request in more than 800ms, so as I didn't want to change the templating engine, I, just like you, decided to compile the Jade views on my development environment and deploy these files instead of original views. 感谢Jade,我开发的最新快速应用程序响应了超过800毫秒的第一个请求,因此我不想更改模板引擎,我和你一样,决定在我的开发中编译Jade视图环境并部署这些文件而不是原始视图。

In order to use the compiled views which are .js files consisting of a function named template , you need to use the jade runtime . 为了使用由名为template的函数组成的.js文件的编译视图,您需要使用jade 运行时 The runtime generates the attribute values and does other stuff like escaping values. 运行时生成属性值并执行其他内容,例如转义值。 The template function accepts one argument which is for dynamic data . template函数接受一个用于动态数据的参数。

Since these functions are compiled for client side, the compiled views depends on a global jade runtime (ie window.jade ). 由于这些函数是为客户端编译的,因此编译的视图依赖于全局jade运行时(即window.jade )。 In node.js you can populate the GLOBAL object, ie GLOBAL.jade = require('jade/lib/runtime') but it's not a good idea. 在node.js中,您可以填充GLOBAL对象,即GLOBAL.jade = require('jade/lib/runtime')但这不是一个好主意。 I decided to modify the compiled function so: 我决定修改编译的函数,所以:

  1. We can require the compiled view ( .js files) by using module.exports . 我们可以通过使用module.exportsrequire编译视图( .js文件)。
  2. The function accepts a second argument which is the jade runtime. 该函数接受第二个参数,即jade运行时。

The following code snippet uses gulp , gulp-jade and gulp-replace node modules in a .gulpfile : 下面的代码段使用gulpgulp-jadegulp-replace中的一个节点的模块.gulpfile

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') );
});

Now that we have changed the function declaration we can load the compiled files ( .js files) instead of the .jade files. 现在我们已经更改了函数声明,我们可以加载编译文件( .js文件)而不是.jade文件。 But there is another problem. 但还有另一个问题。 There is no pre-made templating engine (as far as I know) for using these files. 使用这些文件没有预先制作的模板引擎(据我所知)。 So we need to define a new engine. 所以我们需要定义一个新的引擎。 It's pretty easy: 这很简单:

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);
});

Now we can change the view related settings in express: 现在我们可以在express中更改视图相关设置:

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

Now responding to the first request on startup of the application takes 7ms for me. 现在响应启动应用程序的第一个请求需要7ms。 Just note that require throws error for files that do not exist so you can consider using try/catch or promises for handing the possible exceptions. 请注意,对于不存在的文件, require抛出错误,因此您可以考虑使用try/catch或promises来处理可能的异常。

You can use the jade-runtime module (unofficial). 您可以使用jade-runtime模块(非官方)。 When you do require("jade-runtime") it seems to add a "jade" object to the GLOBAL object so it might just work like that. 当你require("jade-runtime")它似乎将一个“jade”对象添加到GLOBAL对象中,因此它可能就像那样工作。

What has worked for me is prepending the following code to a file that contains the (client-mode) compiled template function. 对我有用的是将以下代码添加到包含(客户端模式)编译模板函数的文件中。

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

See https://github.com/meryn/make-document-html and its Makefile to see it work (the compiled, requirable template function ends up in lib/template.js). 请参阅https://github.com/meryn/make-document-html及其Makefile以查看其工作情况(已编译的,可获取的模板函数最终在lib / template.js中)。 But it could all be done in Node.js itself as well. 但它也可以在Node.js本身完成。

edit 编辑

I need to add that, unless you want to prevent a Jade dependency (as I did), it's not necessary to work with precompiled template files to get the benefits of precompilation. 我需要补充一点,除非你想要阻止Jade依赖(就像我一样),否则没有必要使用预编译的模板文件来获得预编译的好处。 You can just do templateFn = jade.compile(templateCode) somewhere and reuse that. 你可以在某处做templateFn = jade.compile(templateCode)用它。 In fact, I would be surprised if express does not cache the compiled templates itself when you do res.render(templateName, vars) . 事实上,当你执行res.render(templateName, vars)时,如果express不缓存已编译的模板本身,我会感到惊讶。 It would be wasteful if it didn't. 如果没有,那将是浪费。 But I have no experience with express. 但我没有快递经验。 Have you checked what Express render function does? 你有没有检查一下Express渲染功能呢?

you can try the requirejs module which is very easy to use. 你可以尝试一下非常好用的requirejs模块。 In your server side code you can pre-complile your jade files in a folder and then from client side you can call the require function in order to run your pre-compiled template, something like this: 在您的服务器端代码中,您可以在文件夹中预先编译您的jade文件,然后从客户端,您可以调用require函数以运行预编译的模板,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM