注:截止本文完成时,hapi 的版本为:16.4.3
Hapi 并非只能用于开发 API,也可以制作 web app。不过个人觉得如果只是想用 js 来做前端开发的话,找一个更专业的前端框架更合适,比如:AngularJS 或 Vue 等;毕竟 node 的强项并不在此。
做 web app 就离不开“模板”,为了让 hapi 支持渲染模板,需要安装一个名为“vision”的插件。该插件最初是 hapi 内置的,不过在 v9.0 之后就独立出去了,所以需要先安装它:
npm install --save vision
不过,这个 vision 本身并不能独立渲染模板,它还需要配合额外的“模板引擎”才行。在我的理解中,vision 只相当于一个“中介”,它负责帮 hapi 和不同的模板引擎接洽,拿到模板引擎渲染后得到的 HTML 内容再交给 hapi 显示出来。而对于 hapi 来说,并不在乎需要显示的是什么内容,反正完全相信 vision 提供的内容。
Vision 支持的模板引擎有:
应该囊括了知名的 js 模板引擎了。关于这些模板引擎在 vision 下的具体配置方法请参考 vision 主页:https://github.com/hapijs/vision#examples 同时配合 hapi 官方教程:https://hapijs.com/tutorials/views?lang=en_US
鉴于官方教程中使用的是 handlebars 引擎,所以为了跟随它的范例学习,我们还需要安装:
npm install --save handlebars
官方的 views 教程中,迫不及待的介绍了一堆有关 view 的 options,很不友好,给我弄的很迷茫。后来我参考这篇《hapi — How to Render and Reply Views》才写出了一个简单的范例。
本范例中,目录结构如下:
.
├── package.json
├── server.js
└── template
└── index.html
顺便说一句,我生成上述目录结构用的工具是 mac cmd 下的 tree 命令,可以通过 homebrew 安装。
server.js 内容:
'use strict';
const Path = require('path');
const Hapi = require('hapi');
const Hoek = require('hoek');
const server = new Hapi.Server();
server.connection({
port: 3000,
host: 'localhost'
});
server.register(require('vision'), (err) => {
Hoek.assert(!err, err);
server.views({
engines: {
html: require('handlebars')
},
relativeTo: __dirname,
path: 'template'
});
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply.view('index');
}
});
});
server.start();
index.html 内容:
<html>
<body>
<h1>Test Page</h1>
<p>本 html 在结构上偷懒了,凑合看吧。</p>
</body>
</html>
然后访问 http://localhost:3000/ 就应该能看到内容了。
如果你修改一下“范例1”中的 index.html 模板,随便增加点内容后再刷新浏览器会发现页面上毫无变化。这是因为 views 默认会对模板上的内容进行缓存,除非重启 server.js,否则缓存一直都存在。(有人说 hapi 会将这个缓存放在内存中,不知真假,待考证)至于这个缓存有没有默认的过期时间,目前我还不知道,以后搞明白了再补充。
这个缓存功能对于一个正式部署的项目是很有用的;但如果我们只是学习和开发状态下,就可以关闭缓存。具体的方法是调整模板引擎部分的设置:
server.views({
engines: {
html: {
module: require('handlebars'),
isCached: true //这个参数的默认值是 true,设置为 false 就表示关闭缓存了。
}
},
relativeTo: __dirname,
path: 'template'
});
调整之后再尝试修改一下 index.html 后刷新浏览器就可以实时看到变化了。
我想实现的功能是,当访问 http://localhost:3000/hello/Tom 的时候,页面上显示“Hello, Tom!”;而访问 http://localhost:3000/hello/Jack 时被问候的名字就会换成“Jack”。
代码如下:
server.js
'use strict';
const Path = require('path');
const Hapi = require('hapi');
const Hoek = require('hoek');
const server = new Hapi.Server();
server.connection({
port: 3000,
host: 'localhost'
});
server.register(require('vision'), (err) => {
Hoek.assert(!err, err);
server.views({
engines: {
html: {
module: require('handlebars'),
isCached: false
}
},
relativeTo: __dirname,
path: 'template'
});
server.route({
method: 'GET',
path: '/hello/{name}',
handler: function (request, reply) {
const name = encodeURIComponent(request.params.name);
//向模板赋值的方法在这里
reply.view('index', {
name: name
});
}
});
});
server.start();
index.html
<html>
<body>
<h1>Test Page</h1>
<p>Hello, {{ name }}!</p>
</body>
</html>
知道了如何启用和配置模板以及如何为模板上的变量赋值后,官方教程的使命也就结束了。更具体的使用方法就需要参考你所具体选用的模板引擎专属的文档了。