Разработка кастомного шаблона 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 — получите производительность, заточенную под ваш проект.







