我有一个使用 Express 和 Jade(现在是 Pug)的 nodejs 应用程序。我想预编译翡翠模板以获得更好的性能。我已经能够使用jade --client
将所有 .jade 文件编译为相应的 .js 将翡翠转换为 javascript。
如何在我的应用程序中使用这些 js 文件?我对nodejs / express没有太多经验,但我认为它必须需要更改渲染引擎?我已经阅读了说要使用的官方文档,runtime.js
但我找不到任何文档来说明它的使用方式。
Jade(现在的 Pug)是一个很棒的模板引擎,但是视图的编译消耗了很多资源。玉很慢。当然,您可以在生产环境中使用 express 的“缓存视图”功能来缓存已编译的视图,但已编译的视图存储在内存中会消耗大量资源。感谢Jade,我开发的最新的express app 800多毫秒响应了第一个请求,所以我不想改变模板引擎,所以我和你一样,决定编译Jade关于我的开发的意见环境并部署这些文件而不是原始视图。
为了使用编译后的视图,这些.js
文件是由一个名为的函数组成的文件template
,你需要使用jade运行时。运行时生成属性值并执行其他操作,例如转义值。该template
函数接受一个用于动态数据的参数。
由于这些函数是为客户端编译的,编译后的视图依赖于一个全局的翡翠运行时(即window.jade
)。在 node.js 中,您可以填充GLOBAL
对象,即GLOBAL.jade = require('jade/lib/runtime')
,但这不是一个好主意。我决定修改编译后的函数:
require
使用..js
module.exports
以下代码片段使用gulp
,gulp-jade
和gulp-replace
a 中的节点模块.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') );
});
现在我们已经更改了函数声明,我们可以加载已编译的文件(.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'));
现在响应应用程序启动时的第一个请求对我来说需要 7 毫秒。请注意,require
对于不存在的文件会引发错误,因此您可以考虑使用try/catch
or promises 来处理可能的异常。
您可以使用jade-runtime 模块(非官方)。当你这样做时require("jade-runtime")
,它似乎向 GLOBAL 对象添加了一个“jade”对象,所以它可能只是这样工作。
对我有用的是将以下代码添加到包含(客户端模式)编译模板函数的文件中。
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)
。如果没有,那就太浪费了。但是我没有快递的经验。您是否检查过 Express 渲染功能的作用?
您可以尝试使用非常易于使用的 requirejs 模块。在您的服务器端代码中,您可以在一个文件夹中预编译您的翡翠文件,然后从客户端您可以调用 require 函数来运行您的预编译模板,如下所示:
require(['<template_name>'], function (parse) {
document.getElementById(<div_id).innerHTML = parse({
locals: <data_to_be_passed>
})
})