问题
As the first thing I ever try on NodeJS, I'm building a simple app that displays a HTML page which tells visitors their IP address.
Here's how it looks like
var express = require('express');
var app = express();
app.set('view engine', 'mu2');
app.get('/', function (req, res) {
res.setHeader('Content-Type', 'text/html'); // Do I have to do this? I'm not sure.
res.render('frontPage.html', {
ip: req.ip
});
res.send();
});
app.listen(8080, function() {
console.log("Listening on port 8080");
});
Here's how /views/frontPage.html
looks like:
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
</head>
<body>
<h1>Hello, World!</h1>
<hr>
<p>If you're reading this, the NodeJS setup is working. Check your developer console. See if there's any HTTP error in there.</p>
<p>Anyway, your IP address is {{ip}}</p>
</body>
</html>
And here's what I get in the console every time I send a request:
TypeError: this.engine is not a function
at View.render (/Users/macuser/NodeJS/hello/node_modules/express/lib/view.js:126:8)
at tryRender (/Users/macuser/NodeJS/hello/node_modules/express/lib/application.js:639:10)
at EventEmitter.render (/Users/macuser/NodeJS/hello/node_modules/express/lib/application.js:591:3)
at ServerResponse.render (/Users/macuser/NodeJS/hello/node_modules/express/lib/response.js:960:7)
at /Users/macuser/NodeJS/hello/index.js:8:9
at Layer.handle [as handle_request] (/Users/macuser/NodeJS/hello/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/macuser/NodeJS/hello/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/Users/macuser/NodeJS/hello/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/macuser/NodeJS/hello/node_modules/express/lib/router/layer.js:95:5)
at /Users/macuser/NodeJS/hello/node_modules/express/lib/router/index.js:277:22
I already setup frontPage.html
inside views/
and I already installed Moustache from NPM (npm install mu2 --save
).
What's wrong with it?
回答1:
I ended up bypassing Express' template system and use Mustache's own compileAndRender()
. Like this:
var express = require('express');
var app = express();
var mu2 = require('mu2');
mu2.root = __dirname + '/views';
app.get('/', function (req, res) {
var htmlStream = mu2.compileAndRender('frontPage.html', {ip: req.ip});
htmlStream.pipe(res);
});
app.listen(8080, function () {
console.log("Listening on port 8080");
});
It works now.
回答2:
You need to change your file extension from .html to .mu2. res.render('frontPage.mu2', { ip: req.ip});
since it is a Moustache file not an HTML file. You can also leave the file extension off since you set the default view renderer to mu2, and express will use that as the rendering engine if no file extension is provided.
Like this... res.render('frontPage', {ip: req.ip});
. Note that the first part is the file path '/frontPage' and the second part is a local object that you are passing to the template. You would access the ip property of that object something like this {{ip}}
inside your .mu2 file. Moustache returns the rendered HTML to express, and res.render sends it on the the client.
Also, you don't need res.send() since res.render() renders a view, and sends the rendered HTML string to the client, and since text/html is also assumed on responses or type String, you don't need the res.setHeader('Content-Type', 'text-html'); but either. ;)
From expressjs.com
res.render(view [, locals] [, callback]) Renders a view and sends the rendered HTML string to the client. Optional parameters:
locals, an object whose properties define local variables for the view.
callback, a callback function. If provided, the method returns both the possible error and rendered string, but does not perform an automated response. When an error occurs, the method invokes next(err) internally.
The view argument is a string that is the file path of the view file to render. This can be an absolute path, or a path relative to the views setting. If the path does not contain a file extension, then the view engine setting determines the file extension. If the path does contain a file extension, then Express will load the module for the specified template engine (via require()) and render it using the loaded module’s __express function.
来源:https://stackoverflow.com/questions/40934450/typeerror-this-engine-is-not-a-function-when-trying-to-use-moustache-in-express