Содержание
  1. Что такое Pug и зачем он нужен
  2. Установка Pug
  3. Синтаксис Pug: отступы, теги, атрибуты, интерполяция
  4. Переменные, условия и циклы
  5. Миксины: переиспользуемые блоки
  6. Наследование шаблонов: extends и block
  7. Как подключить Pug в Express
  8. Pug против EJS и Handlebars: что выбрать
  9. Недостатки Pug, о которых стоит знать заранее
  10. Итоговый чек-лист по Pug
ГайдыОбновлено · 07.2026

Работаем с шаблонизатором PUG

26 сентября 2023 · 8 минут чтения

Pug (до 2016 года — Jade) — это шаблонизатор и препроцессор HTML для Node.js. Вы пишете разметку без угловых скобок и закрывающих тегов: вложенность задаётся отступами, а данные из приложения подставляются через переменные. Pug компилируется в обычный HTML — на CLI или на лету внутри Express через res.render(). Ниже — полный синтаксис с рабочими примерами, подключение к Express и сравнение с EJS и Handlebars.

Коротко о главном:

  • Отступы вместо тегов — меньше символов, чище вложенность.
  • Переменные #{name}, условия if, циклы each — полноценный JavaScript в шаблоне.
  • Наследование extends / block и миксины mixin убирают дублирование.
  • Нативная интеграция с Express: app.set('view engine', 'pug').
  • Минус — чувствительность к пробелам и лишний шаг компиляции.

Что такое Pug и зачем он нужен

По данным expressjs.com.

Pug — самый популярный язык шаблонов в экосистеме Node.js, написанный на JavaScript. По описанию MDN, это «чистый, чувствительный к пробелам синтаксис для написания HTML, испытавший сильное влияние Haml». Идея простая: браузер всё равно получает HTML, но писать вы его будете компактнее. Первое слово в строке — это HTML-элемент, а отступ следующей строки означает вложенность.

Сравните один и тот же фрагмент. HTML:

<div class="container">
  <h1>Hello, World</h1>
  <p>This is a paragraph.</p>
</div>

Тот же результат на Pug:

.container
  h1 Hello, World
  p This is a paragraph.

Закрывать теги не нужно — структуру держит отступ. На больших страницах это экономит десятки строк и убирает целый класс ошибок с незакрытыми тегами. Мини-вывод: Pug не заменяет HTML, а даёт над ним более лаконичный слой, который затем компилируется обратно в валидную разметку.

Установка Pug

Нужен установленный Node.js. Дальше ставим пакет через npm:

npm install pug

Для разовой компиляции файла в HTML пригодится CLI-утилита:

npm install -g pug-cli
pug index.pug

После команды рядом с index.pug появится готовый index.html. В реальном приложении файлы чаще компилируются не вручную, а автоматически — через шаблонизацию Express (об этом ниже) или сборщик.

Синтаксис Pug: отступы, теги, атрибуты, интерполяция

Разберём базовые кирпичи по порядку — этого достаточно, чтобы верстать реальные страницы.

Теги и вложенность

Имя тега пишется в начале строки, текст — после пробела. Вложенность — отступом (используйте либо только пробелы, либо только табы, не смешивайте):

ul
  li Первый пункт
  li Второй пункт

Классы, идентификаторы и div по умолчанию

Классы задаются точкой, id — решёткой. Если перед .class или #id нет имени тега, Pug подставляет div:

a.button.button--primary(href="/") Кнопка
#main.wrapper
  p Здесь div#main.wrapper

Атрибуты

Атрибуты перечисляются в скобках через запятую. Значения — обычные JavaScript-выражения, поэтому их можно собирать динамически:

a(href="https://example.com", target="_blank", rel="noopener") Ссылка
input(type="checkbox", checked)
img(src="/img/" + fileName, alt=altText)

Интерполяция и текст

Переменная в тексте подставляется через #{...} (значение экранируется), небезопасный HTML — через !{...}. Буферизованный вывод выражения в тег — знаком =. Блок текста задаётся точкой после тега, а строчная разметка — тег-интерполяцией #[...]:

- var user = "Мир"
h1 Привет, #{user}!
p= "Сумма: " + (2 + 2)
p.
  Многострочный
  блок текста.
p Нажмите #[strong сюда], чтобы продолжить.

Комментарии

Двойной слэш даёт видимый HTML-комментарий, //- — «немой», который в вывод не попадёт:

// этот комментарий попадёт в HTML
//- а этот останется только в шаблоне

Переменные, условия и циклы

Строка, начинающаяся с -, — это небуферизованный JavaScript (логика без вывода). Строка с = выводит результат выражения. Данные обычно приходят из приложения, но локальные переменные можно объявлять прямо в шаблоне:

- var items = ["Node", "Pug", "Express"]
- var isAdmin = true

Условия читаются как обычный JavaScript, плюс есть удобный инвертированный unless и case/when:

if isAdmin
  p Панель администратора
else
  p Гостевой режим

unless items.length
  p Список пуст

case status
  when "ok": p Готово
  when "error": p Ошибка
  default: p Неизвестно

Массивы и объекты перебираются через each (со вторым параметром-индексом), а while крутит цикл по условию:

ul
  each item, index in items
    li #{index + 1}. #{item}

- var n = 0
while n < 3
  li Строка #{n++}

Мини-вывод: в отличие от «логически бедных» шаблонизаторов, Pug даёт полный JavaScript. Это гибко, но требует дисциплины — тяжёлую логику лучше держать в контроллере, а в шаблоне оставлять только отображение.

Миксины: переиспользуемые блоки

Миксин — это функция, возвращающая кусок разметки. Объявляется через mixin, вызывается через +. Принимает аргументы и может получать вложенный блок:

mixin card(title, text)
  .card
    h3= title
    p= text

+card("Pug", "Шаблонизатор для Node.js")
+card("Express", "Веб-фреймворк")

Миксин с блоком удобен для оболочек — например, обёртки вокруг произвольного содержимого:

mixin panel(header)
  .panel
    .panel__head= header
    .panel__body
      block

+panel("Заголовок")
  p Любое содержимое внутри панели.

Наследование шаблонов: extends и block

Наследование разбивает сложную страницу на простые файлы. Родительский шаблон описывает общий каркас и объявляет именованные block, а дочерние шаблоны через extends замещают эти блоки. Базовый макет layout.pug:

doctype html
html
  head
    title Мой сайт
    block styles
  body
    block content
    footer © 2026

Дочерняя страница переопределяет только нужные блоки:

extends layout.pug

block content
  h1 Главная
  p Содержимое страницы.

Блок можно не замещать целиком, а дополнять — block append добавит содержимое в конец, block prepend — в начало. Это удобно для подключения страничных стилей поверх общих:

extends layout.pug

block append styles
  link(rel="stylesheet", href="/css/home.css")

Родственный механизм — include: он просто вставляет содержимое другого файла (шапку, подвал, партиал) без логики замещения:

include ./partials/header.pug

Как подключить Pug в Express

Подключить Pug в Express за 4 шага
Подключить Pug в Express за 4 шага

Express «из коробки» умеет работать с Pug — генератор приложений Express даже использует его по умолчанию. Настройка занимает две строки. Укажите папку с шаблонами и движок представления:

const express = require('express');
const path = require('path');
const app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

Создайте шаблон views/index.pug. Данные придут из маршрута через переменные:

html
  head
    title= title
  body
    h1= message

В маршруте вызовите res.render() — первым аргументом имя шаблона (расширение .pug можно опустить), вторым объект с данными:

app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});

Express скомпилирует шаблон при запросе и отдаст клиенту готовый HTML. Никакого ручного вызова pug в этом сценарии не нужно — компиляция встроена в цикл ответа.

Pug против EJS и Handlebars: что выбрать

Pug — не единственный вариант для Express. Три самых частых конкурента отличаются философией: Pug задаёт собственный синтаксис, EJS встраивает JavaScript прямо в HTML (<% %>), а Handlebars использует «логически бедные» усы {{ }}. Сводка по ключевым критериям:

Критерий Pug EJS Handlebars
Синтаксис Свой, на отступах HTML + вставки JS HTML + {{ }}
Порог входа Высокий (новый язык) Низкий (почти чистый HTML) Низкий
Логика в шаблоне Полный JavaScript Полный JavaScript Ограниченная (хелперы)
Наследование макетов Нативно (extends/block) Через partials/include Partials + layout-плагины
Миксины / переиспользование mixin Функции, include Partials, helpers
Валидный HTML на входе Нет (нужна перекомпиляция) Да Да
Многословность Минимальная Высокая Средняя

Практический ориентир. Берите Pug, если цените компактность и активно используете наследование и миксины, а команда готова выучить синтаксис. EJS — когда нужен минимальный порог входа и возможность копировать готовую HTML-вёрстку почти без правок. Handlebars — когда важна строгая изоляция логики от представления (например, шаблоны редактируют не-разработчики).

ОНЛАЙН-ПРАКТИКУМ
ЗАПУСК нейросети DEEPSEEK R1 ЛОКАЛЬНО НА СВОЕМ КОМПЬЮТЕРЕ
ЧТО БУДЕТ НА ОБУЧЕНИИ?
  • ПОКАЖЕМ, КАК РАЗВЕРНУТЬ МОДЕЛЬ нейросети DEEPSEEK R1 ПРЯМО НА СВОЁМ КОМПЬЮТЕРЕ
  • Где и как применять? Потестируем модель после установки на разных задачах
  • Как дообучить модель под себя?

Недостатки Pug, о которых стоит знать заранее

  1. Чувствительность к пробелам. MDN прямо отмечает: лишний пробел «не в том месте» может дать невнятную ошибку. На старте это главный источник боли.
  2. Новый синтаксис. Разработчику, привыкшему к HTML, нужно время на переучивание — и на онбординг новых людей в проект.
  3. Отдельный шаг компиляции. Браузер не понимает Pug напрямую: код всегда нужно превращать в HTML перед отдачей клиенту.
  4. Поддержка в IDE слабее. Инструменты вокруг Pug беднее, чем вокруг чистого HTML, — местами страдают автодополнение и отладка.

Мини-вывод: минусы Pug сводятся к цене входа и дополнительному звену в сборке. Если проект живёт долго и в нём много повторяющейся разметки, эта цена окупается за счёт лаконичности и наследования.

Итоговый чек-лист по Pug

  • Один тип отступа на весь файл — либо пробелы, либо табы.
  • Данные подставляйте через #{} и =, тяжёлую логику держите в контроллере.
  • Повторяющиеся куски — в миксины, общий каркас — в layout.pug с block.
  • В Express достаточно app.set('view engine', 'pug') и res.render().
  • Сомневаетесь в пороге входа команды — сравните с EJS по таблице выше.

Pug — зрелый инструмент, который окупается на страницах со сложной и повторяющейся структурой. Освойте синтаксис, наследование и миксины на небольшом проекте, подключите к Express — и дальше решайте по таблице, подходит ли он вашей команде.

для id="пайтон2" двойной блок курсов не обнаружен

Читайте также

3 материала