呈现基本的HTML视图?

318

我有一个基本的Node.js应用程序,我正在尝试使用Express框架启动它。我有一个views文件夹,其中有一个index.html文件。但是在加载网页时出现以下错误:

Error: Cannot find module 'html'

以下是我的代码。

var express = require('express');
var app = express.createServer();

app.use(express.staticProvider(__dirname + '/public'));

app.get('/', function(req, res) {
    res.render('index.html');
});

app.listen(8080, '127.0.0.1')

我在这里漏掉了什么?

31个回答

315
你可以让 Jade 包含一个纯 HTML 页面:
在 views/index.jade 中:
include plain.html

在views/plain.html文件中

<!DOCTYPE html>
...

而app.js仍然可以渲染jade:

res.render(index)

2
只是想提醒一下,我想要的是仅提供一个 .html 文件,因为我的应用程序是单页面的 ;) - Diosney
1
我们可以使用这种方法包含多个HTML/JS页面吗? - user3398326
15
你应该能够在Express的初始测试中,不使用Jade模板来呈现HTML页面,对吧? - PositiveGuy
1
那我们是不是需要为每个 HTML 文件创建一个 Jade 模板? - Chris - Jr
4
更像是一个hack而不是一个解决方案。 - Ozil
显示剩余4条评论

253

许多答案已过时。

在使用express 3.0.0和3.1.0时,以下内容有效:

app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);

请参考下面的评论,获取express 3.4+的替代语法和注意事项:

app.set('view engine', 'ejs');

那么你可以做如下操作:

app.get('/about', function (req, res)
{
    res.render('about.html');
});

假设您的视图存储在 views 子文件夹中,并且已安装了 ejs Node 模块。如果没有,请在 Node 控制台上运行以下命令:

npm install ejs --save

为什么在这种情况下res.render需要.html扩展名,而在默认的jade情况下不需要呢?使用样板代码时,它只调用 res.render('index', { title: 'Express' });但在这里,它是: res.render('about.html'); - Transcendence
@Transcendence,我不确定。也许你应该开一个新问题。 - Drew Noakes
7
使用 Express 3.4.2 版本:app.set('view engine', 'ejs'); 设置视图引擎为 EJS。 - roland
3
要更新你的package.json文件,应该使用命令“npm install ejs --save”。 - Tom Teman
16
为什么需要使用 EJS? - PositiveGuy
显示剩余5条评论

73

来自Express.js指南:视图渲染

视图文件名采用形式为Express.ENGINE,其中ENGINE是将被要求的模块的名称。例如视图layout.ejs将告诉视图系统去加载require('ejs')这个模块。所加载的模块必须导出方法exports.render(str, options), 以符合Express的要求。但是通过使用app.register(), 可以将引擎映射到文件扩展名,以使例如foo.html由jade进行呈现。

因此,您可以创建自己的简单渲染器,或者您只需使用jade:

 app.register('.html', require('jade'));

点击此处了解更多关于app.register的信息。

请注意,在Express 3中,该方法被重命名为app.engine


57
注意:在 Express 3 中,app.register 已更名为 app.engine。 - Spongeboy
8
请看Andrew Homeyer的回答。那是正确的答案。 - David Betz
7
为了 Express 4,我最终使用了 app.engine('.html', require('ejs').renderFile);。这段代码可以使 Express 使用 EJS 模板引擎渲染 .html 后缀的模板文件。 - CrazyPyro
在 Express 4 中,你也可以使用以下代码: app.set('view engine', 'jade'); - Daniel Huang

62
你也可以读取HTML文件并发送它:
app.get('/', (req, res) => {
    fs.readFile(__dirname + '/public/index.html', 'utf8', (err, text) => {
        res.send(text);
    });
});

26
这个解决方案很糟糕,因为没有对文件进行缓存;每次请求都需要读取文件。 - Marcel Falliere
2
将文件缓存起来其实很容易。只需将读取的文件存储在一个变量中,只有在该变量为空时才重新读取。 您还可以使用JS对象,在各个变量中存储不同的文件,并带有时间戳。虽然这比大多数人所做的工作更费力,但对于新手来说非常好。它很容易理解。 - Naman Goel
7
哎呀,这打败了面向约定的流畅架构(比如MVC)的全部意义。 - David Betz
1
@MarcelFalliere 你假设他想要缓存文件,或者他不想使用自定义缓存解决方案。感谢keegan3d的答案。 - Benny Schmidt
@MarcelFalliere 那么,正确的解决方案是什么?我看到其他答案需要新的依赖项。这只是为了提供HTML文件而必要吗? - JCarlosR
显示剩余4条评论

46

试试这个。它对我有用。

app.configure(function(){

  .....

  // disable layout
  app.set("view options", {layout: false});

  // make a custom html template
  app.register('.html', {
    compile: function(str, options){
      return function(locals){
        return str;
      };
    }
  });
});

....

app.get('/', function(req, res){
  res.render("index.html");
});

2
之前我遇到了一些配置问题,所以我将“.html”中的点去掉,并添加了以下内容:app.set('view engine', 'html'); app.set('views', __dirname + '/views'); 以便完美渲染。 - Bijou Trouvaille
8
有点奇怪……你应该将 HTML 作为静态文件提供。这样还可以获得更好的缓存效果。创建自定义的“HTML 编译器”似乎不太合适。如果需要在路由内发送文件(这种情况很少出现),只需读取并发送即可。否则,请重定向到静态 HTML。 - enyo
2
@Enyo 这条评论似乎有些奇怪,考虑到如何做你所说应该做的事情是被问到的问题,而你的答案只是去做。如何提供带缓存的静态 HTML? - Kyeotic
3
我看到了app.register上的错误。也许在Express 3.0.0.rc3中它已经被弃用了?TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'register' - Drew Noakes
1
@enyo,你没有理解简化架构的重点。当模式是控制器/视图(或/处理器/视图,无论你的具体架构是什么),你不能用过时的扩展模型偏离它。你需要像处理其他内容一样处理你的HTML渲染内容。保持DRY原则,伙计。 - David Betz
显示剩余2条评论

28
app.get('/', function (req, res) {
res.sendfile(__dirname + '/public/index.html');
});

6
sendfile 在生产模式下不会被缓存,因此这不是一个好的解决方案。 - Teo Choong Ping
2
@SeymourCakes 如果我错了,请纠正我,但我认为sendFile现在支持缓存:http://devdocs.io/express/index#res.sendFile - KhoPhi

21

如果您使用的是express@~3.0.0,请将以下行更改为您的示例:


app.use(express.staticProvider(__dirname + '/public'));

变成类似于这样的内容:

app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));

我按照 express api页面上的描述进行了操作,效果非常好。通过这种设置,您无需编写其他代码,因此在微型生产或测试中使用变得足够容易。

下面列出了完整的代码:

var express = require('express');
var app = express.createServer();

app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res) {
    res.render('index.html');
});

app.listen(8080, '127.0.0.1')

1
你为什么在使用 app.listen 启动服务器之后还要重复使用 app.use(express.static(__dirname + '/public')); - fatuhoku
2
将HTML页面作为静态文件提供与使用Express非静态加载有何区别? - PositiveGuy

15

express 3.Xnode 0.6.16中,我也遇到了同样的问题。上面给出的解决方法在最新版本的express 3.x中不起作用。他们删除了app.register方法并添加了app.engine方法。如果您尝试上面的解决方法,则可能会遇到以下错误。

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'register'
    at Function.<anonymous> (/home/user1/ArunKumar/firstExpress/app.js:37:5)
    at Function.configure (/home/user1/ArunKumar/firstExpress/node_modules/express/lib/application.js:399:61)
    at Object.<anonymous> (/home/user1/ArunKumar/firstExpress/app.js:22:5)
    at Module._compile (module.js:441:26)
    at Object..js (module.js:459:10)
    at Module.load (module.js:348:31)
    at Function._load (module.js:308:12)
    at Array.0 (module.js:479:10)
    at EventEmitter._tickCallback (node.js:192:40)

为了消除这个错误消息,请在app.configure函数中添加以下行

app.engine('html', require('ejs').renderFile);

注意:您需要安装ejs模板引擎

npm install -g ejs

示例:

app.configure(function(){

  .....

  // disable layout
  app.set("view options", {layout: false});

  app.engine('html', require('ejs').renderFile);

....

app.get('/', function(req, res){
  res.render("index.html");
});

注意: 最简单的解决方案是使用ejs模板作为视图引擎。在*.ejs视图文件中,您可以编写原始HTML。


3
需要全局安装 ejs 吗? - Drew Noakes
它告诉我找不到 'index.html' 文件。 - MetaGuru

11

文件夹结构:

.
├── index.html
├── node_modules
│   ├──{...}
└── server.js

server.js

var express = require('express');
var app = express();

app.use(express.static('./'));

app.get('/', function(req, res) {
    res.render('index.html');
});

app.listen(8882, '127.0.0.1')

首页.html

<!DOCTYPE html>
<html>
<body>

<div> hello world </div>

</body>
</html>

输出:

你好,世界


9
如果您不需要使用 views 目录,只需将 HTML 文件移动到下面的 public 目录即可。
然后,在 app.configure 中添加此行而不是 '/views'。
server.use(express.static(__dirname + '/public'));

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