Egg.js模板引擎集成:Nunjucks渲染实战
你是否在寻找一种简单高效的方式来构建动态网页?Egg.js作为基于Node.js和Koa的企业级框架,提供了强大的模板渲染能力。本文将带你一步步实现Nunjucks模板引擎在Egg.js项目中的集成与应用,从基础配置到高级功能,让你轻松掌握页面渲染技巧。
为什么选择Nunjucks?
Nunjucks是由Mozilla开发的功能丰富的模板引擎,支持变量替换、条件判断、循环、继承等特性,语法简洁易懂。Egg.js通过egg-view-nunjucks插件提供了对Nunjucks的完美支持,保持了一致的API接口,同时兼顾了性能和安全性。
快速开始:环境准备与插件安装
安装Nunjucks插件
首先,通过npm安装egg-view-nunjucks插件:
npm i egg-view-nunjucks --save
启用插件
在Egg.js项目中,插件配置位于config/plugin.js文件中。添加以下配置启用Nunjucks:
// config/plugin.js
exports.nunjucks = {
enable: true,
package: 'egg-view-nunjucks',
};
核心配置:定制你的模板引擎
Egg.js提供了灵活的配置选项,让你可以根据项目需求定制Nunjucks的行为。主要配置文件为config/config.default.js。
基础配置
// config/config.default.js
const path = require('path');
module.exports = appInfo => {
return {
view: {
root: path.join(appInfo.baseDir, 'app/view'), // 模板文件根目录
mapping: { '.nj': 'nunjucks' }, // 文件后缀与模板引擎映射
defaultViewEngine: 'nunjucks', // 默认模板引擎
defaultExtension: '.nj', // 默认文件后缀
},
nunjucks: {
cache: true, // 生产环境启用缓存
autoescape: true, // 自动转义HTML特殊字符
}
}
};
多目录支持
如果需要从多个目录加载模板,可以将root配置为目录数组:
// config/config.default.js
view: {
root: [
path.join(appInfo.baseDir, 'app/view'),
path.join(appInfo.baseDir, 'app/admin/view'),
].join(',') // 多个目录用逗号分隔
}
模板渲染:三种渲染方式详解
Egg.js在Context对象上提供了三个模板渲染接口,满足不同场景需求:
1. 渲染文件并输出到响应
使用ctx.render()方法渲染模板文件,并自动将结果赋值给ctx.body:
// app/controller/home.js
module.exports = class HomeController extends Controller {
async index() {
const { ctx } = this;
// 渲染app/view/home.nj模板,传入数据
await ctx.render('home', {
title: 'Egg.js + Nunjucks',
user: { name: '访客' },
list: [ 'item1', 'item2', 'item3' ]
});
}
};
2. 渲染文件返回字符串
使用ctx.renderView()方法渲染模板文件,但不自动赋值给ctx.body,而是返回渲染后的字符串:
// app/controller/home.js
async detail() {
const { ctx } = this;
const html = await ctx.renderView('post/detail', {
post: { title: '模板引擎使用指南', content: '...' }
});
// 可以对html进行进一步处理
ctx.body = html.replace(/ Egg /g, ' <strong>Egg</strong> ');
}
3. 渲染模板字符串
使用ctx.renderString()方法直接渲染模板字符串:
// app/controller/home.js
async message() {
const { ctx } = this;
const tpl = 'Hello {{ name }}! Today is {{ date | date("YYYY-MM-DD") }}';
ctx.body = await ctx.renderString(tpl, {
name: 'Egg',
date: new Date()
}, { viewEngine: 'nunjucks' }); // 指定模板引擎
}
模板语法:Nunjucks核心功能示例
变量与过滤器
Nunjucks支持丰富的变量输出和过滤器操作:
<!-- app/view/home.nj -->
<div class="user-info">
<h1>{{ title | upper }}</h1>
<p>欢迎您,{{ user.name | default('Guest') }}</p>
<p>当前时间:{{ now | date("YYYY-MM-DD HH:mm") }}</p>
</div>
条件判断与循环
<!-- app/view/product/list.nj -->
<ul class="product-list">
{% for product in products %}
<li class="{% if loop.index % 2 == 0 %}even{% else %}odd{% endif %}">
<h3>{{ product.name }}</h3>
<p class="price">${{ product.price | round(2) }}</p>
{% if product.stock > 0 %}
<span class="in-stock">有货</span>
{% else %}
<span class="out-of-stock">缺货</span>
{% endif %}
</li>
{% else %}
<li class="no-products">暂无商品</li>
{% endfor %}
</ul>
模板继承与复用
Nunjucks的模板继承功能可以大幅提高代码复用率:
基础模板 (base.nj):
<!-- app/view/base.nj -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}My Site{% endblock %}</title>
<link rel="stylesheet" href="/public/css/style.css">
{% block styles %}{% endblock %}
</head>
<body>
<header>
<h1>My Site</h1>
<nav>{% block nav %}{% endblock %}</nav>
</header>
<main>{% block content %}{% endblock %}</main>
<footer>© 2025 My Site</footer>
{% block scripts %}{% endblock %}
</body>
</html>
子模板 (home.nj):
<!-- app/view/home.nj -->
{% extends 'base.nj' %}
{% block title %}首页 - My Site{% endblock %}
{% block nav %}
<ul>
<li><a href="/" class="active">首页</a></li>
<li><a href="/products">产品</a></li>
</ul>
{% endblock %}
{% block content %}
<h2>欢迎来到首页</h2>
<p>最新公告:{{ notice }}</p>
{% endblock %}
高级特性:Helper与安全渲染
自定义Helper函数
Egg.js允许通过扩展Helper来添加自定义工具函数,在模板中直接使用:
定义Helper:
// app/extend/helper.js
exports.formatPrice = function(price) {
return '¥' + (price / 100).toFixed(2);
};
exports.lowercaseFirst = str => str[0].toLowerCase() + str.substring(1);
在模板中使用:
<!-- app/view/product/item.nj -->
<div class="product">
<h3>{{ helper.lowercaseFirst(product.name) }}</h3>
<p class="price">{{ helper.formatPrice(product.price) }}</p>
</div>
安全渲染与XSS防护
Egg.js内置的egg-security插件提供了安全辅助函数,防止XSS攻击:
<!-- 安全输出HTML内容 -->
<div class="content">{{ helper.shtml(article.content) }}</div>
<!-- 安全生成URL -->
<a href="{{ helper.surl(article.url) }}">阅读全文</a>
调试与最佳实践
开发环境配置
在开发环境中,建议关闭模板缓存,以便实时查看修改效果:
// config/config.local.js
module.exports = {
nunjucks: {
cache: false, // 开发环境关闭缓存
watch: true, // 监听文件变化自动重载
}
};
性能优化
- 生产环境启用缓存:通过
cache: true配置开启模板缓存 - 合理组织模板结构:使用继承和包含减少重复代码
- 避免在模板中编写复杂逻辑:复杂逻辑应在Controller或Service中处理
常见问题与解决方案
Q: 如何在Nunjucks中使用Egg.js的路由函数?
A: 可以通过Helper扩展实现URL生成:
// app/extend/helper.js
exports.pathFor = function(name, params) {
return this.ctx.router.url(name, params);
};
在模板中使用:
<a href="{{ helper.pathFor('product', { id: product.id }) }}">查看详情</a>
Q: 如何在Nunjucks中处理国际化?
A: 结合Egg.js的i18n插件,在模板中使用__函数:
<p>{{ __('welcome.message', user.name) }}</p>
总结与进阶学习
通过本文的介绍,你已经掌握了Nunjucks模板引擎在Egg.js中的基本使用方法。要深入了解更多高级特性,可以参考以下资源:
掌握模板引擎的使用,将大大提高你构建动态网页的效率。无论是开发博客系统、电商平台还是企业网站,Nunjucks与Egg.js的组合都能为你提供强大的支持。
现在,开始动手实践吧!创建你的第一个模板文件,体验Egg.js带来的高效开发体验。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考





