一、HTML模板引擎的前世今生

说起模板引擎,就像装修房子时用的设计图纸。早些年我们做网站开发,都是把HTML代码和业务逻辑混在一起写的,就像把水电管道直接暴露在客厅墙面上一样难看。后来大家发现这样不行,就发明了模板引擎这个好东西。

最早的PHP本身就是个模板引擎,后来出现了Smarty这样的专门工具。现在前端领域常见的模板引擎有EJS、Handlebars、Pug(Jade)等等。它们就像不同风格的设计师,有的喜欢简约,有的偏爱复杂。

举个例子,我们用EJS写个简单的用户列表(技术栈:Node.js + Express + EJS):

<!-- 用户列表模板 userList.ejs -->
<!DOCTYPE html>
<html>
<head>
    <title>用户列表</title>
</head>
<body>
    <h1>系统用户</h1>
    <ul>
        <% users.forEach(function(user){ %>
            <li>
                <%= user.name %> - <%= user.email %>
                <% if(user.isAdmin){ %>
                    <span>(管理员)</span>
                <% } %>
            </li>
        <% }); %>
    </ul>
</body>
</html>
// 后端路由处理
app.get('/users', (req, res) => {
    const users = [
        {name: '张三', email: 'zhang@example.com', isAdmin: true},
        {name: '李四', email: 'li@example.com', isAdmin: false}
    ];
    res.render('userList', {users: users});
});

这个例子展示了EJS的几个特点:

  1. <% %> 里面可以写JavaScript代码
  2. <%= %> 用来输出变量值
  3. 模板逻辑和后端数据完全分离

二、前后端分离的必然趋势

随着Web应用越来越复杂,传统的模板引擎开始显得力不从心。这就好比小饭馆可以一个厨师搞定所有,但大酒店必须前厅后厨明确分工。

前后端分离架构就像把餐厅分成厨房和用餐区,中间通过API传菜。前端专注展示和交互,后端专注数据处理。这种架构下,模板引擎的角色也发生了变化。

以Vue.js为例(技术栈:Vue + Node.js):

// 前端Vue组件 UserList.vue
<template>
    <div>
        <h1>系统用户</h1>
        <ul>
            <li v-for="user in users" :key="user.id">
                {{ user.name }} - {{ user.email }}
                <span v-if="user.isAdmin">(管理员)</span>
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data() {
        return {
            users: []
        }
    },
    created() {
        // 通过API获取数据
        fetch('/api/users')
            .then(res => res.json())
            .then(data => this.users = data);
    }
}
</script>
// 后端API接口
app.get('/api/users', (req, res) => {
    const users = [
        {id: 1, name: '张三', email: 'zhang@example.com', isAdmin: true},
        {id: 2, name: '李四', email: 'li@example.com', isAdmin: false}
    ];
    res.json(users);
});

这种模式下:

  1. 前端完全独立,可以使用任何框架
  2. 后端只提供数据接口,不关心展示逻辑
  3. 前后端可以并行开发

三、现代开发中的模板引擎选择

现在虽然前后端分离是主流,但模板引擎仍然有其用武之地。比如需要SEO的页面、简单的后台系统、电子邮件模板等。

让我们比较几个流行的选择:

  1. EJS:语法简单,类似原始HTML
<!-- 条件判断示例 -->
<% if (user) { %>
    <h2>欢迎, <%= user.name %></h2>
<% } else { %>
    <h2>请登录</h2>
<% } %>
  1. Pug(Jade):简洁的缩进语法
// 同样的条件判断
if user
    h2 欢迎, #{user.name}
else
    h2 请登录
  1. Handlebars:逻辑与模板严格分离
{{#if user}}
    <h2>欢迎, {{user.name}}</h2>
{{else}}
    <h2>请登录</h2>
{{/if}}

选择建议:

  • 需要快速开发:EJS
  • 追求简洁:Pug
  • 需要严格分离:Handlebars
  • 前后端分离项目:直接使用Vue/React模板

四、实战中的架构设计与注意事项

在实际项目中,我们常常需要混合使用多种技术。比如一个电商网站:

  • 商品详情页:用SSR(服务端渲染)保证SEO
  • 用户中心:用前后端分离实现丰富交互
  • 后台管理:直接用模板引擎快速开发

这里给出一个混合架构示例(技术栈:Express + EJS + Vue):

// 服务端入口 app.js
const express = require('express');
const app = express();

// 静态文件和Vue应用
app.use(express.static('public'));

// 传统模板引擎路由
app.set('view engine', 'ejs');
app.get('/product/:id', (req, res) => {
    // 从数据库获取商品数据
    const product = getProductFromDB(req.params.id);
    res.render('productDetail', {product});
});

// API路由
app.get('/api/cart', (req, res) => {
    // 获取购物车数据
    res.json(getCartData());
});

// Vue应用入口
app.get('/user/*', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'user', 'index.html'));
});

注意事项:

  1. 性能:模板引擎渲染会消耗服务器资源,高并发时要考虑缓存
  2. 安全:警惕XSS攻击,特别是使用<%=时要转义输出
  3. 开发体验:前后端分离项目要解决跨域问题
  4. SEO:重要页面考虑预渲染或SSR

五、总结与未来展望

模板引擎就像工具箱里的锤子,前后端分离架构好比电动工具。没有绝对的好坏,关键看用在什么地方。

对于内容型网站,传统的模板引擎仍然简单高效;对于Web应用,前后端分离带来更好的开发体验和性能。未来,随着Edge Computing和Serverless的发展,我们可能会看到更多混合渲染的方案。

无论技术如何变化,核心原则不变:关注用户体验、保证代码质量、选择适合团队的技术栈。就像好厨师不会纠结用中式菜刀还是西式厨刀,重要的是做出美味佳肴。