Разработка кастомного шаблона Umbraco
Клиент приходит с задачей: «Нужен сайт на Umbraco, но готовые темы не подходят — требуется разработка кастомного шаблона Umbraco под нестандартную структуру». Мы не берём шаблон с маркетплейса: пишем Razor-вьюхи, контроллеры и View Components с нуля под конкретный Document Type. Никакой лишней разметки, никаких костылей — только то, что нужно проекту. Кастомный шаблон позволяет загружать страницы на 40% быстрее готового решения за счёт минимизации запросов и bundle splitting.
Как кастомизировать шаблон без потери производительности?
Первый шаг — разобраться с Layout. Каждая страница наследует общий макет, но если в него зашить слишком много логики, пострадает TTFB. Мы выносим статические части (шапка, подвал) в отдельные partials, а динамические — через @await Component.InvokeAsync(). Это даёт кеширование по частям и снижает нагрузку на базу. Например, на одном из проектов LCP упал с 2,8 с до 1,1 с после рефакторинга Layout.
Согласно рекомендациям Google Core Web Vitals, LCP должен быть менее 2.5 секунд. Базовый макет:
@* Views/Shared/_Layout.cshtml *@
@using Umbraco.Cms.Web.Common.PublishedModels
@inject IPublishedValueFallback PublishedValueFallback
<!DOCTYPE html>
<html lang="@System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@ViewData["Title"] – @ViewBag.SiteName</title>
<meta name="description" content="@ViewData["Description"]">
<link rel="stylesheet" href="~/css/app.css" asp-append-version="true">
</head>
<body class="@ViewData["BodyClass"]">
@await Html.PartialAsync("_Navigation")
<main>@RenderBody()</main>
@await Html.PartialAsync("_Footer")
<script src="~/js/app.js" asp-append-version="true" defer></script>
@RenderSection("scripts", required: false)
</body>
</html>Встречается ситуация: клиент хочет, чтобы на каждой странице был свой заголовок h1 и SEO-описание. Решается strongly-typed моделью, которая маппится из IPublishedContent. Мы используем Umbraco Mapper для автоматизации преобразований (подробнее в документации Umbraco).
Пример контроллера статьи на C#:
public class ArticleController : RenderController
{
private readonly IUmbracoMapper _mapper;
private readonly IRelatedContentService _relatedService;
public ArticleController(ILogger<ArticleController> logger, ICompositeViewEngine viewEngine, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoMapper mapper, IRelatedContentService relatedService) : base(logger, viewEngine, umbracoContextAccessor)
{
_mapper = mapper;
_relatedService = relatedService;
}
public override IActionResult Index()
{
if (CurrentPage is not Article article)
return NotFound();
var model = new ArticleViewModel
{
Title = article.Title,
BodyHtml = article.Body?.ToString(),
PublishDate = article.PublishDate,
SeoTitle = article.SeoTitle,
SeoDescription = article.SeoDescription,
CoverImage = article.CoverImage?.First() as IPublishedContent,
Category = article.ArticleCategory?.First() as IPublishedContent,
RelatedArticles = _relatedService.GetRelated(article, 3),
};
return CurrentTemplate(model);
}
} Почему стоит выбирать кастомные шаблоны Umbraco вместо готовых решений?
| Критерий | Готовый шаблон | Кастомный шаблон |
|---|---|---|
| Производительность | Часто перегружен ненужными скриптами | Минимум запросов, оптимизированные Partial View |
| SEO-структура | Разметка фиксирована, сложно менять | Полный контроль над HTML, заголовками, микроразметкой |
| Скорость загрузки | LCP может быть > 2.5 с из-за бандлов | Bundle splitting, lazy images через ImageSharp, WebP |
| Расширяемость | Любая доработка — костыли и патчи | Чистая архитектура, Repository pattern, легко добавлять блоки |
Из таблицы видно, что кастомный шаблон выигрывает по всем ключевым метрикам. Дополнительно, экономия на лицензиях и поддержке может составлять до 30% по сравнению с готовым решением. Стоимость кастомного шаблона ниже, чем покупка и постоянные доработки готового. Сроки разработки прозрачны и фиксируются в ТЗ.
Процесс кастомизации шаблона Umbraco
- Аналитика: изучаем Document Types, структуру контента, требования к производительности.
- Проектирование Layout: создаём макет, определяем зоны для Partial View.
- Разработка контроллеров: пишем strongly-typed ViewModel с внедрением зависимостей для каждого Document Type.
- Реализация блоков: настраиваем Block List / Block Grid с кастомными partials, подключаем ImageSharp для адаптивных изображений.
- Тестирование: проверяем Core Web Vitals, устраняем N+1 запросы, настраиваем кеширование.
- Деплой: передаём код, документацию и доступы.
Этапы разработки и сроки
| Этап | Длительность |
|---|---|
| Аналитика и аудит | 1–2 дня |
| Проектирование Layout | 1–2 дня |
| Разработка контроллеров | 2–4 дня |
| Реализация блоков | 3–5 дней |
| Тестирование и оптимизация | 1–2 дня |
| Деплой и документация | 1 день |
Типичные ошибки при кастомизации шаблонов Umbraco
N+1 запрос — каждый блок Hero независимо загружает изображение. Решение: инжектим сервис изображений в контроллер и передаём готовые URL.
Hydration mismatch — при кешировании частичных вьюх теряется актуальность данных. Используем [OutputCache(NoStore = true)] на динамических компонентах.
Дублирование навигации — многоуровневое меню с отдельными шаблонами для каждого уровня. Вместо этого применяем единый рекурсивный partial _Navigation.
Пример рекурсивной навигации
@* Views/Partials/_Navigation.cshtml *@
@using Umbraco.Cms.Web.Common.UmbracoContext
@inject IUmbracoContextAccessor UmbracoContextAccessor
@{
var ctx = UmbracoContextAccessor.GetRequiredUmbracoContext();
var root = ctx.Content?.GetAtRoot().FirstOrDefault();
var nav = root?.Children.Where(n => n.Value<bool>("showInNav"));
}
<nav class="main-nav">
@foreach (var item in nav ?? [])
{
<a href="@item.Url()" class="@(item.IsAncestorOrSelf(ctx.PublishedRequest?.PublishedContent) ? "active" : "")">
@item.Name
</a>
}
</nav> Что входит в работу
- Разработка Layout и Partial View (навигация, подвал, попапы)
- Strongly-typed модели ViewModel для каждого Document Type
- Контроллеры на C# с внедрением зависимостей
- Блочный редактор (Block List / Block Grid) с кастомными partials
- View Components для макросов (хлебные крошки, меню, виджеты)
- Адаптивные изображения с WebP и srcset
- Минимальная вёрстка Umbraco на Tailwind или CSS Grid — по согласованию
- Документация и доступы (админка, FTP, репозиторий)
Сроки и стоимость
Сроки зависят от числа типов страниц и сложности блоков. Ориентируемся на диапазон:
- Базовый комплект (Layout + 5–6 типов страниц + блоки): 2–3 недели.
- Один сложный шаблон с кастомным контроллером и кешированием: 3–5 дней.
Стоимость рассчитывается индивидуально после аудита текущей структуры. Мы не называем цену вслепую — сначала знакомимся с проектом. Оценим ваш проект за 1 рабочий день, дадим точную смету и сроки. Наш опыт 7+ лет и 50+ проектов на Umbraco позволяют гарантировать предсказуемый результат. Свяжитесь с нами, чтобы обсудить детали — ответим на вопросы. Закажите разработку кастомного шаблона Umbraco — получите производительность, заточенную под ваш проект.







