Слышали про SPA? Это не спа-салон, а Single Page Application — одностраничное приложение. Если вы когда-нибудь пользовались Gmail или Trello, вы уже видели SPA в действии. В этой статье я расскажу, как устроены такие приложения, почему они так популярны и как собрать своё первое SPA на JavaScript. Будет просто, с примерами и без лишней теории.

Digital-студия WNDER

Что такое SPA и с чем его едят

Представьте, что вы пришли в ресторан, где меню — это одна страница, а блюда меняются на ней же, без перехода в другие залы. Вот примерно так работает SPA. Вместо того чтобы каждый раз загружать новую HTML-страницу с сервера, приложение загружается один раз, а дальше JavaScript динамически подменяет содержимое. Пользователь чувствует, что перемещается по сайту, но на самом деле URL может меняться, а страница — нет.

Главные плюсы: скорость (после первой загрузки всё работает быстро), плавные переходы, меньше нагрузки на сервер. Минусы: сложнее SEO (поисковики не всегда дружат с JS), начальная загрузка может быть тяжёлой.

Правило: Если ваш сайт — это в основном контент (блог, новости), SPA может навредить SEO. Для интерактивных приложений (личный кабинет, дашборд) — самое то.

Как работает SPA: маршрутизация без перезагрузки

В обычном сайте каждая ссылка ведёт на новую страницу. В SPA всё иначе: вы кликаете по ссылке, JavaScript перехватывает клик, меняет URL с помощью History API и отрисовывает новый компонент. Сервер отдаёт только начальный HTML, а дальше всё делает клиент.

Простейший пример маршрутизации на чистом JavaScript:

// Простой роутер на основе хеша
window.addEventListener('hashchange', () => {
  const path = window.location.hash.slice(1) || 'home';
  renderPage(path);
});

function renderPage(page) {
  const app = document.getElementById('app');
  if (page === 'home') {
    app.innerHTML = '

Главная

Добро пожаловать!

'; } else if (page === 'about') { app.innerHTML = '

О нас

Мы делаем SPA.

'; } else { app.innerHTML = '

404

Страница не найдена

'; } } // Инициализация renderPage(window.location.hash.slice(1) || 'home');

Этот код слушает изменение хеша (часть URL после #) и вызывает функцию отрисовки. Просто, но уже работает. Для реальных проектов используют библиотеки вроде React Router или Vue Router, но понимание основ поможет не запутаться.

Выбираем инструменты: что подойдёт для SPA

Писать SPA на чистом JavaScript можно, но с ростом сложности хочется автоматизации. Вот несколько популярных вариантов:

Инструмент Плюсы Минусы
Чистый JS Полный контроль, лёгкость Много ручной работы
React Компонентный подход, огромное сообщество Порог входа, нужен сборщик
Vue Простой синтаксис, гибкость Меньше вакансий, чем у React
Svelte Компилируется в чистый JS, быстрый Молодой, меньше экосистема

Для обучения рекомендую начать с чистого JS, а потом перейти на фреймворк. Так вы поймёте, что происходит «под капотом».

Лайфхак: Не тащите в проект фреймворк, если задача решается парой строк на чистом JS. Иногда «просто» — лучше, чем «модно».

Практический пример: собираем мини-SPA

Давайте сделаем простенькое SPA с двумя страницами: главная и контакты. Используем History API для красивых URL без хеша.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Мини SPA</title>
</head>
<body>
  <nav>
    <a href="/" data-link>Главная</a>
    <a href="/contacts" data-link>Контакты</a>
  </nav>
  <div id="app"></div>
  <script src="app.js"></script>
</body>
</html>

А вот JavaScript для него:

const app = document.getElementById('app');

// Функция отрисовки страницы
function render(path) {
  if (path === '/') {
    app.innerHTML = '

Главная

Это SPA без перезагрузки.

'; } else if (path === '/contacts') { app.innerHTML = '

Контакты

Пишите на email@example.com

'; } else { app.innerHTML = '

404

Страница не найдена

'; } } // Перехват кликов по ссылкам document.addEventListener('click', (e) => { if (e.target.matches('[data-link]')) { e.preventDefault(); const href = e.target.getAttribute('href'); history.pushState({}, '', href); render(href); } }); // Обработка кнопок назад/вперёд window.addEventListener('popstate', () => { render(window.location.pathname); }); // Начальная отрисовка render(window.location.pathname);

Этот код перехватывает клики по ссылкам с атрибутом data-link, меняет URL без перезагрузки и вызывает render. При нажатии «назад» срабатывает popstate, и страница перерисовывается. Уже похоже на настоящее SPA!

Совет: Чтобы сервер не возвращал 404 при обновлении страницы по адресу /contacts, настройте его на отдачу index.html для всех маршрутов. Это называется fallback.

Подводные камни и как их обойти

SPA — это не серебряная пуля. Вот несколько проблем, с которыми вы столкнётесь:

  • SEO: Поисковики могут не выполнять JS. Решение: серверный рендеринг (SSR) или пререндеринг.
  • Начальная загрузка: Большой бандл JS замедляет первый показ. Решение: разделение кода (code splitting) и ленивая загрузка.
  • Управление состоянием: С ростом приложения становится сложно следить за данными. Решение: использовать паттерны вроде Redux или Vuex.

Не бойтесь начинать с малого. Сделайте простой SPA, почувствуйте, как это работает, а потом углубляйтесь.

Что в итоге

Одностраничные приложения на JavaScript — это мощный инструмент для создания быстрых и интерактивных веб-приложений. Они не всегда нужны, но если вы делаете дашборд или соцсеть, без них не обойтись. Начните с чистого JS, чтобы понять механику, затем выбирайте фреймворк по вкусу. И помните: главное — чтобы пользователю было удобно, а не чтобы было модно.

Экспериментируйте, пробуйте, ошибайтесь — так вы научитесь. Удачи в создании вашего первого SPA!

Студия WNDER