Mục lục

    Nếu bạn đang làm việc trong hệ sinh thái Node.js, đặc biệt là với framework Express.js, chắc hẳn bạn đã từng nghe hoặc được khuyên sử dụng EJS. Vậy EJS là gì và tại sao nó lại phổ biến đến vậy?

    Với tư cách là một chuyên gia JavaScript, tôi có thể khẳng định EJS là một trong những công cụ “nhỏ mà có võ”, giúp giải quyết bài toán hiển thị dữ liệu động (Server-Side Rendering) một cách thanh lịch và hiệu quả.

    EJS là gì? Embedded JavaScript Template Engine cho Node.js

    Nói một cách đơn giản, EJS (Embedded JavaScript) là một template engine (công cụ tạo mẫu) cho phép bạn tạo ra các tệp HTML động bằng cách nhúng mã JavaScript trực tiếp vào bên trong tệp HTML.

    EJS là gì
    EJS là gì

    Hãy tưởng tượng HTML là khung xương, CSS là giao diện, thì EJS chính là “bộ não” logic (JavaScript) được tích hợp ngay trong khung xương đó, cho phép bạn điều khiển nội dung hiển thị trước khi nó được gửi đến trình duyệt của người dùng.

    Giải thích sâu hơn: EJS hoạt động như thế nào?

    Khác với các template engine khác có thể bắt bạn học một cú pháp hoàn toàn mới (như Pug), EJS giữ mọi thứ đơn giản. Nó tuân theo triết lý: “Nếu bạn biết HTML và JavaScript, bạn đã biết EJS.”

    EJS hoạt động như thế nào
    EJS hoạt động như thế nào

    EJS hoạt động ở phía máy chủ (server). Quá trình diễn ra như sau:

    1. Client Request: Người dùng yêu cầu một trang web (ví dụ: /profile).
    2. Server Process: Máy chủ Node.js của bạn nhận yêu cầu, truy vấn cơ sở dữ liệu để lấy thông tin người dùng (ví dụ: user = { name: "Gemini" }).
    3. EJS Render: Bạn gọi hàm res.render() và truyền tệp EJS (profile.ejs) cùng với dữ liệu (user).
    4. EJS Compilation: EJS “đọc” tệp .ejs của bạn, tìm tất cả các thẻ đặc biệt của EJS, thực thi mã JavaScript bên trong chúng (ví dụ: thay thế <%= user.name %> bằng “Gemini”), và biên dịch nó thành một tệp HTML thuần túy.
    5. Server Response: Máy chủ gửi tệp HTML đã được biên dịch (HTML tĩnh) này về cho trình duyệt của người dùng.

    Điều này cực kỳ quan trọng vì nó giúp trang web của bạn tải nhanh hơntốt hơn cho SEO, vì robot của Google nhận được HTML đầy đủ nội dung thay vì một trang “trống” phải chờ JavaScript phía client chạy.

    Tại sao nên chọn EJS? (Ưu điểm nổi bật)

    Mặc dù có nhiều template engine khác (như Pug, Handlebars), EJS vẫn có chỗ đứng vững chắc nhờ các ưu điểm sau:

    • Rất dễ học và sử dụng: Bạn không cần học cú pháp mới. Chỉ cần viết HTML và “rắc” thêm JavaScript vào nơi bạn cần. Điều này giúp các lập trình viên frontend và thiết kế viên dễ dàng hợp tác.
    • Linh hoạt tuyệt đối: Vì nó là “Embedded JavaScript”, bạn có thể sử dụng toàn bộ sức mạnh của JavaScript (vòng lặp for, câu lệnh if/else, switch/case, gọi hàm…) ngay trong template của mình.
    • Hiệu suất cao: EJS biên dịch các mẫu (templates) thành các hàm JavaScript được tối ưu hóa, giúp tốc độ render rất nhanh.
    • Tích hợp chặt chẽ với Express.js: Express “hiểu” EJS một cách tự nhiên. Chỉ cần một dòng app.set('view engine', 'ejs') là bạn đã sẵn sàng.
    • Hỗ trợ Layouts và Partials (Includes): EJS cho phép bạn dễ dàng tái sử dụng code HTML.
      • Partials (Includes): Cho phép bạn tạo các “mảnh” HTML (như header.ejs, footer.ejs) và nhúng chúng vào nhiều trang khác nhau.
      • Layouts: Giúp bạn định nghĩa một “khung” chung cho trang web và chỉ cần thay đổi phần nội dung chính.

    Xem thêm:

    Cú pháp EJS cơ bản bạn phải biết

    Để “ra lệnh” cho EJS, bạn sử dụng các thẻ (tags) đặc biệt. Đây là những thẻ quan trọng nhất:

    Cú pháp EJS cơ bản bạn phải biết
    Cú pháp EJS cơ bản bạn phải biết

    Thẻ <%= ... %> (Output Escaped)

    Đây là thẻ bạn sẽ dùng nhiều nhất. Nó dùng để hiển thị giá trị của một biến hoặc biểu thức JavaScript ra HTML.

    • Escaped (Thoát ký tự): EJS sẽ tự động “thoát” các ký tự HTML đặc biệt (như <, >, &). Điều này cực kỳ quan trọng để chống lại các cuộc tấn công XSS (Cross-Site Scripting).

    Ví dụ:

    Nếu biến username<script>alert('hack')</script>, EJS sẽ render ra:

    HTML
    <h2>Xin chào, <%= username %></h2>
    
    <h2>Xin chào, &lt;script&gt;alert('hack')&lt;/script&gt;</h2>

    Thẻ <%- ... %> (Output Unescaped)

    Thẻ này cũng dùng để hiển thị giá trị, nhưng nó không thoát ký tự. Nó sẽ render ra HTML thô.

    Cảnh báo bảo mật: Chỉ sử dụng thẻ này khi bạn tuyệt đối tin tưởng vào nguồn gốc của dữ liệu (ví dụ: nội dung bài post được tạo từ một trình soạn thảo Rich Text Editor của quản trị viên). Không bao giờ dùng nó để hiển thị dữ liệu do người dùng nhập trực tiếp.

    Ví dụ:

    HTML
    <div class="post">
        <%- postContent %>
    </div>
    
    <div class="post">
        <h1>Bài viết mới</h1>
        <p>Nội dung...</p>
    </div>

    Thẻ <% ... %> (Scriptlet Tag)

    Đây là thẻ dùng để thực thi logic JavaScript mà không tạo ra bất kỳ kết quả hiển thị nào. Bạn dùng nó cho vòng lặp, điều kiện, khai báo biến…

    Ví dụ kinh điển (Vòng lặp for):

    HTML
    <ul>
        <% users.forEach(function(user) { %>
            <li><%= user.name %></li>
        <% }); %>
    </ul>
    

    Ví dụ (Điều kiện if/else):

    HTML
    <% if (user) { %>
        <h2>Chào mừng, <%= user.name %>!</h2>
    <% } else { %>
        <h2>Vui lòng <a href="/login">Đăng nhập</a></h2>
    <% } %>

    Các thẻ hữu ích khác

    • <%# ... %>: Thẻ comment (ghi chú). Nội dung bên trong sẽ bị bỏ qua.
    • <%- include('partials/header') %>: Dùng để nhúng một tệp EJS khác (partials) vào vị trí hiện tại.

    Hướng dẫn: Ví dụ EJS với Express.js (Hello World)

    Hãy xem một ví dụ thực tế để thấy EJS là gì và nó hoạt động ra sao.

    Bước 1: Cài đặt

    Đầu tiên, bạn cần cài đặt expressejs:

    Bash
    npm install express ejs

    Bước 2: Cấu hình Express (app.js)

    Tạo tệp app.js (hoặc server.js):

    JavaScript
    const express = require('express');
    const app = express();
    const port = 3000;
    
    // 1. Chỉ định Express sử dụng EJS làm view engine
    app.set('view engine', 'ejs');
    
    // 2. (Tùy chọn) Chỉ định thư mục chứa các tệp EJS
    // Mặc định là thư mục 'views'
    // app.set('views', './my-views-folder');
    
    // 3. Tạo một route để render trang
    app.get('/', (req, res) => {
        // Dữ liệu bạn muốn gửi sang EJS
        const data = {
            title: "Trang chủ EJS",
            message: "Chào mừng bạn đến với EJS!",
            users: [
                { id: 1, name: "Alice" },
                { id: 2, name: "Bob" },
                { id: 3, name: "Charlie" }
            ]
        };
    
        // 4. Render tệp 'index.ejs' và truyền dữ liệu
        // Express sẽ tự động tìm tệp 'views/index.ejs'
        res.render('index', data);
    });
    
    app.listen(port, () => {
        console.log(`Server đang chạy tại http://localhost:${port}`);
    });

    Bước 3: Tạo tệp EJS (views/index.ejs)

    Tạo một thư mục tên là views và bên trong nó, tạo tệp index.ejs:

    HTML
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title><%= title %></title>
    </head>
    <body>
        <h1><%= message %></h1>
    
        <h2>Danh sách người dùng:</h2>
        <ul>
            <% users.forEach(function(user) { %>
                <li>ID: <%= user.id %> - Tên: <%= user.name %></li>
            <% }); %>
        </ul>
    
        <hr>
    
        <%- include('partials/footer') %> 
    </body>
    </html>
    

    Bây giờ, khi bạn chạy node app.js và truy cập http://localhost:3000, bạn sẽ thấy một trang HTML hoàn chỉnh với dữ liệu đã được lấp đầy.

    Kết luận

    EJS là gì? EJS là một công cụ mạnh mẽ, trực quan và không rườm rà. Nó là “cầu nối” hoàn hảo giữa logic phía máy chủ (Node.js) và giao diện người dùng (HTML).

    Nếu bạn đang tìm kiếm một giải pháp Server-Side Rendering mà không muốn “học lại từ đầu”, EJS chính là lựa chọn lý tưởng. Sự đơn giản trong việc kết hợp HTML và JavaScript thuần túy làm cho nó trở thành một công cụ không thể thiếu trong bộ công cụ của nhiều lập trình viên Node.js.

    Hy vọng bài viết này đã giúp bạn hiểu rõ EJS là gì và cách để bắt đầu sử dụng nó trong các dự án của mình.


    Bạn có muốn tôi giải thích thêm về cách sử dụng partials và layouts trong EJS để tối ưu hóa cấu trúc dự án không?

    4.7/5 - (3 bình chọn)

    Để lại một bình luận

    Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

    Chào mừng bạn đến với TASDIGITAL.net
    Chào mừng bạn đến với TASDIGITAL.net