Express EJS shabloni bilan ishlash

Hozirgacha server ikki narsa qaytardi: JSON yoki tayyor statik HTML fayl. Lekin sahifa ma’lumot bilan to’ldirilgan HTML bo’lishi kerak bo’lsa-chi? Vazifalar ro’yxatini serverda tayyorlab, foydalanuvchiga to’liq sahifa yuborish kerak. Shablon aynan shu ish uchun.

Muammo: HTML ni qo’lda yopishtirish

Ma’lumotni HTML ga qo’shishning noto’g’ri yo’li:

// ❌ Bunday yozilmaydi
app.get("/tasks", (request, response) => {
  let html = "<h1>Vazifalar</h1><ul>";

  for (const task of tasks) {
    html = html + "<li>" + task.title + "</li>";
  }

  html = html + "</ul>";
  response.send(html);
});

Uch muammo bor. HTML tuzilishi JavaScript qatorlari orasida yo’qoladi. Tahrirlash uchun kod ichini kavlash kerak. Eng jiddiysi — task.title ichida <script> bo’lsa, u brauzerda bajariladi.

Shablon shu uchala muammoni yechadi.

EJS ni ulash

O’rnatamiz:

npm install ejs

Serverga ikki qator qo’shamiz:

const express = require("express");
const path = require("path");

const app = express();

// Shablon dvigatelini tanlaymiz
app.set("view engine", "ejs");

// Shablonlar qaysi papkada turishini aytamiz
app.set("views", path.join(__dirname, "views"));

app.listen(3000, () => {
  console.log("Server ishga tushdi: http://localhost:3000");
});

app.set("view engine", "ejs") yozilgandan keyin require("ejs") kerak emas — Express paketni nomi bo’yicha o’zi topadi.

views papkasini yarating. Loyiha tuzilishi:

express-app/
├── public/
│   └── style.css
├── views/
│   └── tasks.ejs
├── app.js
└── package.json

Birinchi shablon

views/tasks.ejs faylini yarating:

<!DOCTYPE html>
<html lang="uz">
  <head>
    <meta charset="UTF-8" />
    <title><%= pageTitle %></title>
    <link rel="stylesheet" href="/style.css" />
  </head>
  <body>
    <h1><%= pageTitle %></h1>
    <p>Jami: <%= tasks.length %> ta vazifa</p>
  </body>
</html>

Marshrutda response.render() chaqiriladi:

const tasks = [
  { id: 1, title: "Kitob o'qish", isDone: false },
  { id: 2, title: "Kod yozish", isDone: true },
];

app.get("/tasks", (request, response) => {
  // Birinchi argument — fayl nomi (.ejs yozilmaydi)
  // Ikkinchi argument — shablonga uzatiladigan ma'lumot
  response.render("tasks", {
    pageTitle: "Vazifalar ro'yxati",
    tasks: tasks,
  });
});

Brauzerda http://localhost:3000/tasks ni oching:

Vazifalar ro'yxati
Jami: 2 ta vazifa

response.render() uch ish qiladi: views papkasidan tasks.ejs ni topadi, uzatilgan obyekt kalitlarini shablonga o’zgaruvchi sifatida beradi va tayyor HTML ni yuboradi.

Ikki teg — eng muhim farq

EJS da qiymat chiqaradigan ikki teg bor. Ular o’xshash ko’rinadi, lekin farqi juda jiddiy.

Teg Nima qiladi
<%= qiymat %> Qiymatni ekranlab chiqaradi
<%- qiymat %> Qiymatni xom HTML sifatida chiqaradi

Farqni misolda ko’ramiz. Aytaylik, foydalanuvchi vazifa sarlavhasiga shunday matn yozdi:

<script>alert("Saytingiz buzildi")</script>

Bu matn <%= task.title %> bilan chiqarilsa, brauzerda aynan shu qator matn sifatida ko’rinadi — hech narsa bajarilmaydi. Sahifa manbasida esa ekranlangan shakli turadi:

&lt;script&gt;alert("Saytingiz buzildi")&lt;/script&gt;

Xuddi shu matn <%- task.title %> bilan chiqarilsa, brauzer uni haqiqiy <script> tegi deb qabul qiladi va kodni ishga tushiradi.

Yodda saqlash uchun qisqa qoida: tenglik belgisi (=) xavfsiz, chiziq (-) xavfli.

Sikl va shart

EJS ichida to’liq JavaScript ishlaydi. Buning uchun <% %> — tengliksiz teg ishlatiladi. U kod bajaradi, lekin hech narsa chiqarmaydi.

views/tasks.ejs ni to’ldiramiz:

<!DOCTYPE html>
<html lang="uz">
  <head>
    <meta charset="UTF-8" />
    <title><%= pageTitle %></title>
    <link rel="stylesheet" href="/style.css" />
  </head>
  <body>
    <h1><%= pageTitle %></h1>

    <% if (tasks.length === 0) { %>
      <p>Hozircha vazifa yo'q.</p>
    <% } else { %>
      <ul>
        <% for (const task of tasks) { %>
          <li>
            <%= task.title %>
            <% if (task.isDone) { %>
              <strong>(bajarildi)</strong>
            <% } %>
          </li>
        <% } %>
      </ul>
    <% } %>
  </body>
</html>

Brauzerda:

Vazifalar ro'yxati
  • Kitob o'qish
  • Kod yozish (bajarildi)

Uch teg turini ajratib oling:

Teg Vazifa Misol
<%= %> Qiymat chiqaradi, ekranlaydi <%= task.title %>
<%- %> Qiymat chiqaradi, ekranlamaydi Ishonchli HTML uchun
<% %> Kod bajaradi, chiqarmaydi <% if (...) { %>

include bilan takrorni yo’qotish

Har sahifada <head>, menyu va futer takrorlanadi. EJS ularni alohida faylga chiqarish imkonini beradi.

views/partials papkasini yaratib, ichiga ikki fayl qo’ying.

views/partials/header.ejs:

<!DOCTYPE html>
<html lang="uz">
  <head>
    <meta charset="UTF-8" />
    <title><%= pageTitle %></title>
    <link rel="stylesheet" href="/style.css" />
  </head>
  <body>
    <nav>
      <a href="/tasks">Vazifalar</a>
      <a href="/about">Biz haqimizda</a>
    </nav>

views/partials/footer.ejs:

    <footer>
      <p>Vazifalar ilovasi</p>
    </footer>
  </body>
</html>

Endi views/tasks.ejs qisqaradi:

<%- include("partials/header") %>

<h1><%= pageTitle %></h1>

<ul>
  <% for (const task of tasks) { %>
    <li><%= task.title %></li>
  <% } %>
</ul>

<%- include("partials/footer") %>

Yangi sahifa qo’shish endi oson:

app.get("/about", (request, response) => {
  response.render("about", { pageTitle: "Biz haqimizda" });
});

views/about.ejs:

<%- include("partials/header") %>

<h1><%= pageTitle %></h1>
<p>Bu ilova Express va EJS bilan yozilgan.</p>

<%- include("partials/footer") %>

Menyuni o’zgartirish kerak bo’lsa, header.ejs ni bir marta tahrirlaysiz — hamma sahifada yangilanadi.

Shablon va API — ikkalasi birga

Bitta ilovada ikki xil javob yashay oladi:

// Brauzer uchun — HTML sahifa
app.get("/tasks", (request, response) => {
  response.render("tasks", { pageTitle: "Vazifalar ro'yxati", tasks: tasks });
});

// Dastur uchun — JSON
app.get("/api/tasks", (request, response) => {
  response.json(tasks);
});

Farqni ajrating: /tasks ni odam brauzerda ochadi, /api/tasks ga esa boshqa dastur yoki fetch murojaat qiladi.

Javob turi Kim uchun Metod
HTML sahifa Brauzerdagi foydalanuvchi response.render()
JSON Frontend kodi, mobil ilova response.json()

Server sahifani tayyorlab yuborishi CSR, SSR va SSG darsida tasvirlangan usullardan biri.

Amaliy mashq

express-app loyihasida davom eting:

  1. ejs ni o’rnatib, app.set("view engine", "ejs") va views yo’lini sozlang;
  2. views/tasks.ejs yaratib, pageTitle ni <%= %> bilan chiqaring;
  3. for sikli bilan vazifalarni ro’yxat qilib chiqaring va bajarilganiga (bajarildi) qo’shing;
  4. Massivga sarlavhasi <b>Qalin</b> bo’lgan vazifa qo’shing va uni <%= %> bilan chiqaring — teg matn bo’lib ko’rinishini tasdiqlang;
  5. Xuddi shu qiymatni vaqtincha <%- %> ga o’zgartirib, matn qalin bo’lib qolishini ko’ring, so’ng darhol <%= %> ga qaytaring;
  6. partials/header.ejs va partials/footer.ejs yaratib, ikki sahifada include bilan ulang.

4 va 5-qadam birga eng muhimi: ikki tegning farqini o’z ko’zingiz bilan ko’rasiz. Sinovda <b> tegi ishlatilgani bejiz emas — u zararsiz, lekin farqni aniq ko’rsatadi.

Qisqacha xulosa

  • Shablon — o’rinbosarlari ma’lumot bilan to’ldiriladigan HTML fayl.
  • EJS ikki qator bilan ulanadi: app.set("view engine", "ejs") va app.set("views", ...).
  • response.render("tasks", { ... }) shablonni topadi, to’ldiradi va yuboradi; kengaytma yozilmaydi.
  • <%= %> ekranlaydi va xavfsiz, <%- %> xom HTML beradi va foydalanuvchi ma’lumoti uchun xavfli.
  • Ekranlanmagan foydalanuvchi matni XSS hujumiga yo’l ochadi.
  • <% %> tegi kod bajaradi: if va for shu bilan yoziladi.
  • include takrorlanadigan bo’laklarni bir joyga yig’adi va bitta ilova ham HTML sahifa, ham JSON qaytara oladi.

Keyingi darsda yakuniy loyiha — CRUD API, shablon va statik fayllarni bitta ishlaydigan ilovaga birlashtiramiz.

Bu dars foydali bo'ldimi?

marta ko'rildi