Как создать spa приложение
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents Loading
Copy raw contents
Copy raw contents
Задачка на создание SPA приложения
- сложность: средняя
- требуемые знания: JS, DOM, HTML/CSS, один из серверных языков
- время: 2-3 месяца
SPA значит «Single Page Application», то есть приложение, работающее в браузере без перезагрузки страницы. Это позволяет сделать работу с приложением более удобной для пользователя, а также реализовать поддержку оффлайн-режима (работы при временном отсутствии соединения с интернетом).
Необходимо сделать SPA приложение для преподавателей университета. Доступ к приложению возможен только после регистрации и одобрения администратором. Приложение должно позволять просматривать, создавать и редактировать информацию о расписании занятий в учебном заведении, о посещаемости и успеваемости студентов. Приложение должно поддерживать работу в оффлайн-режиме на планшете.
Вся информация хранится на сервере, и параллельно может работать много экземпляров приложений.
Вот как выглядят основные экраны приложения (посмотреть в высоком SVG качестве):
Если ты следишь за миром JS, то наверно знаешь что в последние несколько лет появилось немало фреймворков и библиотек для создания SPA:
- Backbone (старый) - предоставляет роутер и основу для написания моделей, контроллеров и вью. Реализует события и подписку на них для моделей, но не предоставляет готовой реализации view.
- Knockout - шаблонизатор, реализующий подход data binding
- Angular 2 - фреймворк для разработки SPA, содержащий в себе все нужные компоненты, начиная с роутера и заканчивая шаблонизатором с data binding.
- React - библиотека, предоставляющая реализацию View для MVC приложений с поддержкой автоматического обновления данных на странице
- Vue.js - библиотека, реализующая View для MVC приложений.
Таким образом, у тебя есть выбор из как минимум:
- backbone + knockout (сейчас особо не используется)
- angular 2 (тебе придется изучить TypeScript, ковырять исходники и документацию ангулар, уроков уровня hello world недостаточно)
- react + redux
- vue.js
Для этого стоит использовать HTML 5 History API.
Данные хранятся на сервере, я рекомендую использовать реляционную SQL базу данных для этого. Сервер также занимается аутентификацией пользователей, проверкой доступа, проверкой правильности переданной информации. Необходимо реализовать серверное API, через которое приложение будет обменивать данными с сервером. Есть как минимум такие варианты:
Для повышения скорости обмена данными можно применять трюки вроде группировки запросов.
Хорошо бы генерировать документацию для API. В случае REST это можно сделать инструментом вроде Swagger.
Реализовать серверную часть можно на любом языке. Например, на PHP с использованием микрофреймворков Silex или Slim, или на Node.JS (платформа для реализации сервера на яваскрипте).
В валидации данных возможно тебе чем-то поможет стандарт json-schema.
В JS-приложении в любой момент может произойти ошибка. Разумеется, нужно проинформировать пользователя об этом, предложив ему перезагрузить приложение.
Также, все произошедшие на клиенте ошибки должны логгироваться на сервере (как иначе разработчик узнает о них?). Достаточно просто писать их в лог-файл, с подробностями ошибки, стек-трейсом (при наличии), id пользователя, времени прошедшем от запуска приложения.
Нужно логгировать версию клиента, так как при частых релизах активными могут быть несколько версий приложений-клиентов.
Приложение должно приложить максимум усилий к сохранению введенных пользователем данных. Потеря связи с сервером или выключение питания устройства не должно приводить к потере введенных данных.
Для этого тебе придется использовать локальное хранилище данных в браузере и настроить очередь синхронизации, которая накапливает изменения и при появлении связи с сервером выгружает их.
Надо подумать что делать в случае возникновения конфликтов, попытки внести 2 разными клиентами противоречащие друг другу изменения.
В случае отсутствия связи с сервером приложение должно сохранять введенные данные в локальном хранилище для последующей отправки их на сервер. Там же можно кешировать ранее полученные с сервера данные. Надо понимать что приложение будет использоваться на мобильных устройствах с ненадежной связью.
Приложение должно реализовать наиболее комфортную работу с данными в таких условиях.
Возможно также стоит использовать HTML5 app manifest, который позволяет браузеру загружать приложение из кеша при отсутствии сети.
Отладочная и продакшен версия
При разработке удобно хранить код в большом количестве небольших файлов. И сделать так, что при перезагрузке страницы все изменения становятся видны сразу. Но это неэффективно для боевой версии приложения, так как оно будет медленно загружаться. Потому стоит настроить систему сборки (assets pipeline) которая будет собирать все в один файл для продакшена.
Для этого удобно использовать инструмент gulp, написанный на яваскрипте.
Сторонние библиотеки нужно подключать через менеджер пакетов вроде bower.
Когда у тебя много маленьких файлов, трудно отслеживать вручную их зависимости и понимать, в каком порядке их надо склеивать. Эту проблему решает система модулей, есть как минимум две:
- AMD (asynchronous modules definition)
- Common.JS
Соответственно есть сборщики и загрузчики этих модулей. Один их последних это webpack, поддерживающий по моему оба формата.
В новом стандарте ES6 появились ES6 Modules, которые поддерживают самые новые браузеры. Наверно, есть смысл использовать их в коде, но компилировать с помощью webpack в массово поддерживаемый формат.
Изоморфным называют код, который может выполняться и на клиенте и на сервере. При разработке SPA мы можем натолкнуться на проблему, как сделать наш код изоморфным. Вот зачем это нужно:
- нам нужны одинаковые модели на клиенте и на сервере
- иногда нам нужно иметь возможность генерировать страницы на сервере (в этой задаче не нужно)
- нам нужны правила валидации данных и на модели и на сервере
Одно из решений - использовать один и тот же язык на клиенте и сервере, и специальное окружение, сглаживающее различия между ними.
Версионирование API, версионирование приложения, миграции
Со временем серверное API будет меняться. Но что если старый клиент попробует обратиться к такому API? Очевидно, может произойти ошибка или, что хуже, данные потеряются. Чтобы этого избежать, можно применить версионирование API, явно добавив версию API в URL:
Посл выхода новой версии API можно отдавать старым клиентам уведомление о том что они устарели.
Аналогичная проблема возникает с хранилищем. Представь приложение версии 1 сохранило данные в хранилище на клиенте, а на следующий день пользователь запустил приложение версии 2. Сможет ли оно прочесть данные? Для решения этой проблемы можно:
- явно помечать версию данных в хранилище и при обнаружении несоответствия запускать функцию миграции данных. Она должна быть реализована так, чтобы не терять данные при ошибке или закрытии вкладки браузера.
- писать код чтения данных из хранилища так, чтобы он мог читать данные от старых версий приложения
При этом стоит помнить о таких вещах:
- миграция может быть продолжительной и прерваться (пользователь закрыл браузер, компьютер завис). Стоит писать миграции так, чтобы они не разрушали какие-то данные и их можно было без ущерба перезапустить заново. Например, вместо изменения таблицы можно создавать новую, а затем атомарно переименовывать ее, заменяя старую. Или вместо удаления данных только добавлять их.
- пользователь может открыть несколько копий приложения в нескольких вкладках. Что если они одновременно запустят процесс миграции, не будет ли конфликтов? Бороться с этим можно взятием блокировки на время миграции.
Также, если все важные данные уже сохранены на сервере, можно отказаться от миграций и вместо этого просто уничтожать старую базу данных в браузере и создавать новую.
Хорошо бы покрыть приложение или его компоненты автоматическими тестами
Поддержка разной плотности пикселей
Для этого можно либо использовать векторные SVG-картинки либо генерировать иконки в нескольких разрешениях.
Анимация при правильном использовании помогает сконцентрировать внимание пользователя на нужном элементе интерфейса или проиллюстрировать происходящее событие.
Проверка возможностей браузера
Перед запуском приложение должно проверять наличие в браузере всех нужных ему возможностей и уведомлять пользователя об их отсутствии. Аналогично оно должно поступать при отключенном JS.
Одностраничные приложения (SPA) имеют мнжество преимуществ, таких как скорость, по-настоящему хороший UX, и полный контроль HTML-разметки. Становится всё больше и больше сайтов SPA; всё больше инструментов, которые упрощают процесс разработки SPA. Вы, вероятно уже читали о молодом и перспективном фреймворке Vue.js. Предлагаю вам глубже погрузиться в Vue и на конкретном примере разобраться с простым SPA.
Мы напишем клиент-серверное приложение простейшего блога. Приложение будет отображать список записей а также полный текст каждой отдельной записи. И само собой, всё это будет происходить без перезагрузки страницы.
Ознакомившись с примером этого приложения, вы научитесь извлекать данные в Vue, создавать роуты и разберётесь с интересной особенностью Vue — однофайловыми компонентами.
Бэкенд
Фронтенд
Инструменты
Начать работу с Vue очень просто. С использованием правильных инструментов это ещё проще. Рекомендую взглянуть на проект vue-awesome, который содержит список инструментов, компонентов, библиотек и плагинов на все случаи жизни.
Vue-cli
При создании нового проекта рекомендуется воспользоваться Vue-cli. Так можно создавать проекты с использованием официальных шаблонных проектов Vue, или одного из множества шаблонных проектов с открытым исходным кодом, и, конечно же, вы можете создать свой собственный и использовать его в любом месте.
Итак, для начала установим vue-cli в качестве глобального пакета:
Затем проинициализируем проект с выбранным шаблоном; для нашего примера более чем достаточно использовать webpack-simple.
Далее перейдём в папку vue-spa и запустим npm install в терминале. После установки всех пакетов, мы можем запустить наше приложение в режиме разработки.
Эта команда автоматически запустит наш проект на локальном dev-сервере webpack. В браузере появится наше простейшее приложение Vue. Конечно оно выглядит совсем не так, как бы нам хотелось, и годится лишь в качестве отправной точки для начала чего-то большего. Чтобы продолжить работу, предлагаю сначала ознакомиться со структурой нашего шаблона.
Шаблон webpack-simple
Внутри шаблон webpack-simple имеет следующую структуру:
Файл index.html содержит простую разметку HTML с единственным элементом “app” в body. Он будет заменён на DOM, сгенерированный vue. По этой причине тэг body не рекомендуется использовать в качестве корневого элемента.
В папке src лежит файл main.js, который содержит точку входа webpack. Компоненты Vue импортируются там же. Ещё там описан корневой экземпляр Vue, который пока что имеет два свойства. Свойство ‘el’ обеспечивает экземпляру Vue связь с указанным DOM элементом. Ещё одно — функция отрисовки, генерирующая DOM из App.vue. В общем, это все, что нам нужно знать о структуре шаблона webpack-simple, не так много, не так ли? Основная часть нашего приложения будет запрограммирована в App.vue. Расширение .vue определяет файл как однофайловый компонент vue. Это одна из особенностей Vue с которой мы сейчас познакомимся поближе.
Однофайловые компоненты
Каждый файл *.vue состоит из блоков трёх типов: <template>, <script> и опционально <style>. В результате, мы можем разделить проект на связанные компоненты. Внутри компонента его шаблон, логика и стили неотъемлемо связаны, и их совмещение фактически делает компонент более целостным и легко поддерживаемым. Теперь мы готовы приступить к созданию блога на Vue.
Пишем приложение
Давайте посмотрим, что собственно мы собираемся реализовать. У нас будет заголовок с названием нашего блога в верхней части страницы. С левой стороны у нас будет фиксированная боковая панель, в которой мы будем отображать заголовки наших записей, это будет что-то вроде оглавления. Остальная часть страницы будет занята динамическим блоком, в котором будет отображаться сам текст записи.
Шаг 1
Прежде всего, удалим все лишние строки из App.vue. И перепишем шаблон в соответствии с нашими требованиями.
После первого обращения, вы больше не сможете добавлять реактивные свойства к корневому объекту данных. Поэтому, прежде чем создавать экземпляр Vue, рекомендуется объявить все реактивные свойства на уровне корня.
Шаг 2
Затем импортируем его в компонент App и определим метод getAllPosts() который будет делать запрос к серверу и присваивать его свойству posts. Вызываем метод в хуке created(), который будет вызываться после создания экземпляра Vue и после установки настроек обращения к данным.
А теперь отобразим все заголовки записей в боковой панели.
До сих пор мы отображали только заголовки записей, но пока мы ещё не можем видеть сами записи. Теперь необходимо отобразить полный пост в разделе контента в соответствии с выбранным названием на боковой панели. В то же время хотелось бы, чтобы каждая запись была доступна по своему уникальному адресу.
Шаг 3
Для этого воспользуемся официальной Vue библиотекой vue-router. Как уже понятно из названия, библиотека позволяет настраивать роутинг для нашего приложения.
Установим библиотеку:
Для настройки роутинга вернёмся к файлу main.js. Здесь мы определим настройки роутинга и добавим их в наш экземпляр Vue.
В настройках роутинга мы указали, какой компонент вызывает отрисовку по соответствующему пути. Поскольку только компонент Post.vue будет отвечать за отрисовку каждого поста, нам не потребуется определять путь к каждому посту, достаточно определить динамический путь.
Этот путь содержит динамический сегмент :id который указывает на конкретный пост. При этом у нас есть доступ к этому сегменту в компоненте Post через this.$route.params.id. Однако использование $route в нашем компоненте закрепит жесткую связь с роутом, что в свою очередь ограничивает гибкость компонента, поскольку он может использоваться только на определенных URL-адресах. Вместо этого мы можем использовать опцию props и установить её в true. После этого $route.params станет связан с опцией props компонента Post.
Теперь, когда мы создали роутер, мы можем вернуться к нашему приложению и добавить еще несколько строк в шаблон.
Здесь мы имеем два компонента vue-router: <router-link> и <router-view>. Первый — это компонент для включения навигации пользователя в приложении с поддержкой роутинга. Второй компонент — это функциональный компонент, который отрисовывает согласованный компонент для данного пути.
Остался заключительный шаг. Нам нужно отобразить содержимое записи поста.
Шаг 4
Перейдём к файлу Post.vue, в котором добавим простой шаблон:
Затем нам нужно установить параметры экземпляра Vue для этого компонента. Здесь все также как в настройках отображения всех постов. Объявим опцию props с меняющимся id, которая будет получать номер нашего поста. Далее, объявим объект данных, как уже делали в App.vue:
Затем опишем метод getPost(), который будет получать только одну запись поста по идентификатору и вызовем его в хуке created().
Теперь всё работает так, как и должно. Чтобы получить версию для продакшина достаточно выполнить команду npm run build в консоли.
Сейчас существует два подхода при создании веб-приложений: традиционные веб-приложения, большая часть логики которых выполняется на сервере, а также одностраничные приложения, логика пользовательского интерфейса которых выполняется преимущественно в веб-браузере, а взаимодействие с веб-сервером осуществляется главным образом через AJAX, а навигация по сайту происходит без перезагрузки страниц. За счет такой архитектуры, SPA-приложения работают быстрее, чем «традиционные» сайты.
На рисунке ниже показано отличие традиционного веб-приложения от SPA-приложения.
Плюсы SPA-приложений
- Высокая скорость и отзывчивость приложения
- Не требуется server-side рендеринг
- Уменьшение затрат на разработку backend
- Возможность вместо собственного backend использовать сторонние API сервисы
Минусы SPA-приложений
- Плохо индексируются поисковыми системами
- SPA-приложения не работают без включенного JS в браузере
Исходя из-того, что написано выше можно сделать вывод, что архитектуру SPA можно использовать при разработке следующих типов приложений: crm системы, панели управления, личные кабинеты, приложения для информационных киосков, приложения для ПК (Electron App).
Описание проекта
Поэтому предлагаю, разработать SPA приложение "Агрегатор новостей". В процессе разработки будем использовать фреймфорк Total.js и библиотеку jComponent .
Мы напишем клиент-серверное приложение, которое будет искать новостные посты со всего мира, по определенным параметрам, после чего выводить их в удобном для нас виде. Сделаем такие разделы приложения, как настройки, история просмотра постов, топ новостей по определенной категории, и поиск новостей. Разумеется, это все будет работать без перезагрузки страниц.
Принципы работы Single Page Applications
Прежде чем приступить к разработке, нужно понять следующее у SPA приложений все пользовательские «передвижения» должны фиксироваться в истории навигации. При этом навигация должна быть «глубокой». Другими словами, если пользователь откроет скопированную ссылку на внутренний модуль в другом окне или, например, браузере, он должен попасть на необходимую ему страницу. Что бы реализовать подобное необходимо использовать History Api.
Разработка SPA приложения предусматривает использование только одной страницы. Следовательно, все необходимое для функционирования этого приложения (скрипты, стили и т.д.) должно размещаться на единственной веб-странице.
SPA приложение предусматривает загрузку всех необходимых скриптов в процессе инициализации веб-страницы.
SPA загружает дополнительные модули «по требованию» пользователя.
Сегодня есть множество фреймворков, реализующих принцип SPA. Но сейчас я буду использовать библиотеку jComponent , в которую отдельно включена библиотека jRouting library, которая позволяет реализовать навигацию по SPA приложению.
Шаг 1
Перед созданием самого приложения, я сделал простую верстку. Для быстрого создания прототипа использовал фреймворк Bootstrap 3.2 У меня получилась следующая композиция. Сверху навигация, снизу блок,
именно в эту область мы будем подгружать динамические блоки в зависимости от нужного нам функционала.
Шаг 2
В качестве фреймфорка для бэкенда будем использовать Totaljs . Для начала установим фреймворк следующей командой. Фреймворк из npm репозитария будет установлен в папку node-modules .
После чего в этой же папке создадим папки, как на рисунке
Немного о структуре папок, которые я создал на сервере.
- conrollers - в этой папке размещаем описание маршрутов (рут)
- definations - здесь размещаем описание определений для фреймворка, этим самым мы будем менять поведение фреймворка
- modules - здесь находится различные функциональные модули, которые расширяют возможности нашего приложения
- public - в этой папке будем размещать css , javascript , изображения, вообщем дополнительные ресурсы, которые нужны нашему приложению в браузере
- views - в ней находятся шаблоны, которые необходимы фреймворку для рендеринга на стороне сервера, там будет находится всего один файл index.html , эта будет именно та страница, которую выдаст наш сервер при обращении.
Шаг 3
Разберемся, с тем как у нас будет работать сервер.
Маршрутизация
В папку controllers разместим файл default.js . В котором описаны все маршруты для нашего приложения.
Модули
Ресурсы
В папке public разместим наши ресурсы css и javascript . И в отдельной подпапке part разместим дополнительные части нашего приложения. Эти части будут подгружаться в наше SPA приложение в раздел body . Примеры наших частей:
Сжатие и оптимизация ресурсов для клиента
Теперь в папку definitions добавим файл merge.js . Дело в том, что в Total.js встроен минификатор, который минифицирует и объединяет javascript и css файлы. Это позволит уменьшить в размере ресурсы, которые будут передаваться на клиент.
Теперь вместо нескольких фалов, на клиент будет передано всего три файла spa.min.js , app.min.js и app.min.css при этом они будут минифицированы. На мой взгляд это очень удобно, ненужно использовать никаких дополнительный модулей для сборки типа grunt.js или gulp.js .
Шаг 4
Теперь займемся самым интересным будем писать само приложение для клиента. Файл назовем app.js и разместим его на сервере в папке public/js .
Инициализация
Проведем инициализацию настроек. Сами настройки будем хранить в localStorage , если они отсутствуют, будем использовать значение по умолчанию.
Инициализируем объект common в котором будут текущие настройки нашего приложения, текущая страница, номер страницы и другие данные.
Навигация
Как я писал выше навигация в SPA приложении немного отличается от обычной и для того, чтобы нам её реализовать обратимся к библиотеке jRouting.js . Для начала изменим нашу навигацию и добавим в наши ссылки класс R . Получим следующее:
Теперь инициализируем ссылки. Если пользователь нажмет на ссылку с классом .R , то будет выполнен внутренний REDIRECT(перенаправление) при этом браузер не выполнит классическое перенаправление на серверную часть, а будет использоваться внутренний обработчик.
Если переменная common.page меняется, то автоматически, произойдет подгрузка и смена определенной части, если нужная часть, ранее была подгружена, то просто сменится часть. Для этого в файле index.html в body сделаем соответствующую разметку, будем использовать компонент j-Part .
Обработчики для загрузки новостей
Сохранение настроек
При нажатии на кнопку Save options будет вызвана функция save_option() , если форма заполнена корректна, то сохраним настройки в кэше (localStorage).
Статистика просмотра новостей
Заключение
В этом посте я постарался объяснить, что такое SPA приложение и чем они отличаются от традиционных. Кроме этого написали небольшое SPA приложение. Навигация реализуется с помощью библиотеки jRouting , которая в свою очередь входит в библиотеку jComponent , при клике по специальной ссылке мы подгружаем в body нужную нам часть. Также на некторых страницах используем компонент lazyload , который в свою очередь в нужный для нас момент обращается к серверу через AJAX с определенными параметрами, сервер в свою очередь создаёт запрос к стороннему API, после чего передаёт результат назад клиенту, клиент используя шаблон формрует страницу с превьюшками новостей и выстраивает в виде адаптивной сетке используя библиотеку massondry.js .
В моих примерах можно найти SPA приложение без использования серверной части. В дальнейшем я хочу на основе этого приложения сделать полноценное Electron приложение.
React.js – замечательный фреймворк для фронтенд-разработки. У него удобный интерфейс и большие возможности, которые лучше всего реализуются при создании одностраничных приложений. Сегодня мы запилим небольшое Single Page Application и параллельно разберёмся в некоторых принципах React.
MPA vs SPA
Схема работы классического многостраничного приложения
В классическом Multi Page Application каждый url – это отдельный запрос к серверу с получением нового шаблона.
Схема работы SPA – одностраничного приложения на React
В итоге браузер отдал только одну страницу – index.html .
Сложно ли сделать SPA?
Несложно. Если вы используете инструменты из экосистемы React, то большая часть рутинной работы уже сделана за вас. Сосредоточьтесь на логике приложения, а скучное обновление DOM-дерева оставьте библиотеке.
Что нужно знать? Чтобы разобраться в React, достаточно знать на базовом уровне JavaScript версии ES6. Если неуверены в скиллах, то чекните их в нашей статье Больше JS, чем React: как фреймворк использует возможности языка.
Основы работы React
DOM. Загружаясь на страницу, скрипт берёт под контроль DOM-элемент, который вы ему предоставили. Теперь внутри этого элемента безраздельно властвует React. Он может отслеживать действия пользователя и менять дерево элементов на любом уровне. Для этого используется быстрый виртуальный DOM. В этот элемент может выводиться любой компонент (или дерево компонентов) в зависимости от текущего состояния приложения. Могут меняться какие-то мелочи или даже весь контент целиком.
JSX. Привычной MVC-модели в React нет, так как в компоненте объединяется и представление (рендер), и логика. Это значит, что в компоненте, например, селекта, вы определяете и его внешний вид, и поведение. Для удобства используется специфический JSX-синтаксис (JavaScript XML). Он похож на HTML, но на самом деле это чистой воды JavaScript. Убедиться в этом и поиграться вы можете в онлайн-компиляторе Babel.
Компиляция JSX-кода в обычный JavaScript
Мы не будем подробно разбираться в тонкостях JSX. Если вы с ним незнакомы, то загляните сначала в Подробное руководство по JSX в React, а потом продолжайте чтение.
Запуск проекта
Настройка webpack. Настраивать всю среду разработки с чистого листа было бы долго и скучно. Воспользуемся готовым решением – утилитой create-react-app. Она подготовит начальную структуру проекта, скачает необходимые зависимости и настроит webpack. Если вы плохо знакомы с принципами сборки проекта, загляните во вводное руководство по webpack (и перестаньте уже его бояться).
Откройте рабочую директорию, запустите терминал – начинаем работать.
В директории появилась новая папка react-spa . Заходим в папку, запускаем команду:
Запустится сервер для локальной разработки, и в браузере откроется новая вкладка с текущим проектом.
Исходники. Все интересующие исходники лежат в папке src :
- src/index.js – входная точка сборки. Здесь указывается корневой DOM-элемент, в который помещается главный компонент App , представляющий собой наше React-приложение.
- src/App.js – это собственно код компонента App .
А другие файлы? Помимо этих файлов, в папке src лежат стили, тесты, несколько служебных скриптов и svg-файл логотипа – всё это нам сейчас неважно. Основные боевые действия будут разворачиваться внутри App.js .
В документации React подробно описано, что такое компонент и как с ним работать. Нам же сейчас достаточно понимать, что компонент – просто функция, которая принимает извне некоторые свойства ( props ), а возвращает разметку для рендера в формате JSX.
Первая страница
Наше SPA будет представлять собой портфолио React-разработчика.
Откройте файл src/App.js , удалите всё ненужное, и разместите следующий код:
Стили можете написать свои или взять готовые:
Используя JSX-синтаксис и удобные фичи типа циклов, мы создаём разметку простой страницы с шапкой, блоком приветствия и списком выполненных проектов.
На что обратить внимание:
- Вместо атрибута class используется className ;
- Все теги, включая img , должны быть закрыты; используется метод map ;
- Каждый элемент массива, создаваемого методом map , должен иметь уникальный ключ key .
Структура проекта и компоненты
Заботимся о структуре. Если продолжить писать всё в одном файле, SPA очень быстро разрастётся, и мы запутаемся в коде. Нужно разделить проект на отдельные компоненты.
Сейчас у нас наметились несколько самостоятельных блоков:
- Header – шапка с брендом;
- About – блок с приветствием;
- PortfolioItem – карточка одного проекта.
Создадим директорию src/components , а внутри – отдельные папки для каждого компонента. Код и стили блоком переносим практически без изменений:
src/components/Header/Header.js src/components/About/About.js src/components/PortfolioItem/PortfolioItem.js
Подключаем компоненты внутри App:
Что изменилось? В качестве уникального ключа для элементов массива мы теперь используем id проекта, а не порядковый индекс элемента. Эта практика лучше, так как позволяет React оптимизировать рендер.
Директория src теперь выглядит так:
Файловая структура проекта
Все исходники можно посмотреть здесь. Визуально ничего не изменилось.
Чем больше проект, тем важнее становится его структура. Загляните в большое руководство по структурированию react-проектов, чтобы создавать удобные и легко поддерживаемые приложения.
Взаимодействие с пользователем
Добавляем формы. Теперь нужно научить наше SPA отслеживать действия пользователя и реагировать на них. Для демонстрации лучше всего подходят формы, поэтому мы добавим форму обратной связи в наше портфолио. Вот так это будет выглядеть на странице.
Форма обратной связи. Добавляем новый компонент ContactForm .
Обработчики событий. У ContactForm есть также методы-обработчики событий onSubmit (отправка формы) и onChange (изменение значений полей). Поля ввода полностью контролируются React – мы отслеживаем ввод и указываем, что выводить. Чтобы лучше понять, что такое контролируемые компоненты и как происходит изменение данных в формах, загляните в документацию React.
Храним состояние формы. Теперь у компонента App появляется состояние: форма может быть закрытой или открытой. Чтобы хранить этот параметр переделаем App из функционального компонента (stateless) в классовый и добавим ему поле state .
Внизу разместим кнопку, клики по которой будем отслеживать с помощью атрибута onClick .
Обратите внимание: Для изменения состояния компонента предназначен метод this.setState , который принимает новый объект состояния. Подробнее о состоянии вы можете прочитать в документации.
Добавим в приложение страницы. Хоть мы и используем React, до сих пор в нашем проекте не было ничего особенного. Мы работаем в пределах одной страницы, отслеживаем события и меняем DOM. Чтобы прикоснуться к магии Single Page Application, нужно в наше приложение добавить страниц. Например, было бы неплохо показывать детальную информацию о выполненном проекте по адресу /projects/ .
Требования к маршрутизации SPA:
Пакет react-router-dom. Не переживайте, нам не придётся заниматься этим вручную. Честно говоря, нам вообще мало что придётся делать – всё уже сделано. Пакет react-router инкапсулирует логику маршрутизации, а react-router-dom обеспечивает его взаимодействие с DOM в браузере.
Теперь откройте файл src/index.js и оберните всё приложение в компонент BrowserRouter .
Файловая структура проекта src/pages/home/index.js src/pages/project/index.js
Сами маршруты мы определим прямо в компоненте App, но в реальном приложении, вы, вероятно, захотите указать их в отдельном файле для удобства.
Все исходники вы можете найти здесь. Демонстрационная версия приложения имеет ограниченную функциональность – нет редиректа на главную при вводе несуществующего маршрута.
На что обратить внимание:
- Идентификатор конкретного проекта передается прямо в url как параметр :id .
- Извлечь его в компоненте можно из this.props.match.params.id .
- В методе componentDidMount компонента ProjectPage можно сделать запрос к серверу для получения данных проекта. В коде задержку запроса имитирует метод setTimeout .
- Все внутренние ссылки (в компонентах Header и ProjectPreview ) заменены на компонент Link , это обеспечивает переход между маршрутами без перезагрузки.
- Компонент App больше не имеет состояния – оно перешло в компонент HomePage – поэтому его снова можно сделать функциональным.
Чтобы глубже разобраться в работе роутера, загляните в этот туториал по использованию React Router.
Время чтения: 8 минут
Что такое одностраничные приложения?
Одностраничные приложения (SPA, Single-Page Application) — это веб-приложения или веб-сайты, которые состоят из одной HTML-страницы. Они подключаются к серверу только один раз, а затем просто динамически подгружают и обновляют данные. Ключевые элементы интерфейса страницы остаются неизменными, обновляются только те блоки, которые использует пользователь (например, переключается между вкладками или разделами).
Главное преимущество одностраничных приложений : не нужно перезагружать всю страницу, чтобы обновить контент. Это позволяет увеличить скорости загрузки и улучшить опыт взаимодействия с продуктом (UX).
Лучше один раз увидеть, как работает SPA, чем десять раз прочитать описание. Вспомните свой почтовый ящик — не важно, пользуетесь вы Gmail, Mail или Yandex — это один из популярных примеров одностраничных приложений. Не важно, что вы делаете в приложении: пишите письмо, ищите старый емэйл или чистите папку «Спам», боковая панель с папками, шапка страницы и логотип сайте всегда останутся неизменными. Это и есть SPA!
Примеры одностраничных приложений
Сейчас все больше компаний выбирает одностраничные приложения из-за их скорости работы и сроков разработки. Существует множество SPA, которые мы используем ежедневно и даже не осознаем этого этого.
Спорим, сегодня вы пользовались одностраничным приложением ? Мы собрали несколько известных примеров, чтобы проверить эту гипотезу.
Да-да, веб-приложение Gmail — это одностраничное приложение . Когда вы открываете веб-страницу, то первые пару секунд видите индикатор загрузки — это означает, что данные загружаются с сервера. Как только все готово, вы получаете доступ к письмам. Пока вы пишите письма и переключаетесь между папками, левая и правая боковые панели, а также заголовок вверху будут преследовать вас везде.
Gmail, как и многие другие почтовые агенты, является одностраничным приложением.
По сути, большинство сервисов Google являются одностраничными приложениями . Еще один пример от компании — Google Docs. Вы можете печатать или прокручивать страницу, чтобы прочитать документ — шапка с настройками текста и левая боковая панель с заголовками останутся на месте. Приложение периодически обновляет время последнего изменения и подгружает новые комментарии к файлу.
Google Docs — еще один пример SPA, которые мы используем каждый день.
Неожиданно, но факт: Netflix также является одностраничным приложением , несмотря на количество контента, которое в нем содержится. Чтобы убедиться, просто зайдите в свою учетную запись, попробуйте переключиться между разделами, и вы увидите как заголовок с логотипом будут оставаться на месте, а фильмы и сериалы будут обновляться, пока вы скролите вниз и листаете фильмы.
SPA могут отлично справляться с большим количеством контента – Netflix тому пример.
Существуют разные мнения о том, можно ли считать Facebook полноценным одностраничным приложением . Скорее всего, истина где-то посередине и социальная сеть — это частично SPA.
Архитектура ленты новостей Facebook выстроена как одна бесконечная динамичная страница.
Кстати, а вы подписаны на нас в социальных сетях? Там можно найти больше советов и рекомендаций по UI/UX дизайну и разработке MVP. Рекомендуем заглянуть !
Приложение для бронирования жилья — еще один классический пример SPA, которым мы пользуемся на регулярной основе. Если откроете поисковую страницу, пролистаете результаты, переключитесь между вкладками и посмотрите профиль квартиры, вы заметите, что хедер страницы с логотипом Airbnb, строка поиска и информация вашего профиля в верхнем левом углу будут оставаться без изменений.
Даже когда мы выбираем жилье на Airbnb, мы используем SPA.
миллионов человек по всему миру.
READ MORE Как создать маркетплейс вроде Airbnb? Отвечаем на популярные вопросыПлюсы одностраничных приложений
Почему крупные компании все чаще и чаще предпочитают одностраничные приложения для своих решений? Мы нашли 3 основные причины:
- Скорость работы и отзывчивость приложения.
- Возможность переиспользовать код.
- Улучшенный пользовательский опыт.
Давайте нырнем глубже и подробно разберем основные преимущества SPA!
1. Скорость и отзывчивость. Самое главный плюс одностраничных приложений — время загрузки. Из-за того, что SPA не требует полностью перезагружать страницу во время использования, контент на странице обновляется очень быстро. Приложению нужно только установить первоначальное соединение с сервером в начале, а затем просто подгружать отдельные компоненты, когда это необходимо пользователю.
показало, что каждые 0,1 секунды ожидания загрузки страница обходятся Amazon в 1% продаж, что равно миллиардам долларов США. А для поисковика Google дополнительные 0,5 секунды задержки снижают трафик на 20%.
Поэтому тот факт, что одностраничным приложениям требуется меньше времени для загрузки, повышает удовлетворенность пользователей и коэффициент удержания (CRR).
2. Возможность переиспользования кода. Если в будущем вы решите расширить свое одностраничное приложение и превратить его в полноценное мобильное приложение, то 20%-30% кода можно будет использовать повторно, вместо того, чтобы писать всё с нуля. Плюс, это поможет вашему стартапу сэкономить время и снизить затраты.
3. Улучшенный UX. При работе с одностраничным приложением пользователям не нужно долго ждать загрузки — после первого раза все работает быстро. Кроме того, когда продукт подгружает данные, пользователи могут видеть состояние загрузки и прикинуть, как долго осталось.
Минусы одностраничных приложений
О дностраничные приложени я хороши, но это не панацея для стартапа. У SPA тоже есть минусы. Вот четыре основных:
READ MORE Фотографы, $250 тысяч инвестиций и 300 экранов «какого-то» дизайна. Кейс Purrweb1. SEO. Одностраничные приложения сложно оптимизировать для SEO. Если разместить все ключевые слова на одной странице, это будет выглядеть как минимум странно. Плюс, у страницы будет только один URL-адрес.
Проблему индексации поисковыми системами можно решить с помощью Server Side Rendering.
SSR (Server Side Rendering, серверный рендеринг) — способ рендеринга одностраничного приложения на стороне сервера, когда в браузер пользователя отправляется уже полностью отрисованная страница.
Решение будет по-прежнему одностраничным, а основная работа будет на сервере. При первой загрузке приложение получит готовую страницу с сервера с необходимыми SEO-элементами. Но из-за внедрения этой технологии стоимость разработки SPA может увеличиться.
2. Скорость изначальной загрузки. Это палка о двух концах. Когда пользователь только открывает приложение, браузер загружает страницу с сервера, поэтому приходится немного подождать. Зато после загрузки, все остальные данные будут подгружаться динамически, и ждать больше не придется.
Но если над архитектурой SPA работали профессионалы, то пользователи не столкнутся с этой проблемой. Они будут загружать не все приложение целиком, а лишь необходимую часть, а в дальнейшем решение просто будет подгружать отдельные компоненты.
Мы ответим на это одним словом: «роутинг». Проблема перехода по кнопкам легко решается еще на этапе разработки.
Роутинг страниц — важная фича в навигации по одностраничному приложению. Она позволяет настроить маршрутизацию внутри приложения так, что пользователь сможет перемещаться по истории одной вкладки без перезагрузки всей страницы.
4. Уязвимость приложения. Это минус не только одностраничного решения, но и вообще всех веб-приложений. Они могут быть более уязвимы для программных атак, которые используют межсайтового скриптинга (XSS, от англ. Cross-Site Scripting). С помощью XSS хакеры могут вставлять вредоносный код на страницу и в браузеры пользователей.
Однако эту проблему можно решить, если внимательно отнестись к защите конечных точек данных (data endpoint), поэтому мы рекомендуем уделить особое внимание безопасности данных первичной страницы.
Почему SPA — это тренд 2021?
, что больше половины всего веб-трафика приходилось на мобильные устройства, но конверсия на них была ниже, чем с десктопов.
С началом пандемии пользователи стали больше времени проводить в интернете: сидеть в социальных сетях, заказывать доставку продуктов и общаться по Zoom. Поэтому требования к скорости и UX тоже возросли — пользователи ждут, что страницы будут загружаться быстро, а купить желаемое можно будет в два клика.
, что время загрузки страницы напрямую связано с процентом отказов (bounce rate) , когда пользователи уходят без покупки. Например, если время загрузки возрастает с 1 до 5 секунд, то отказы увеличиваются на 90%. А если с 1 до 10 секунд, то шансы потерять клиента повышаются на 123%.
Одностраничные приложения — это удобное решение для разработки MVP в 2021 году. Оно позволяет создать простой и отзывчивый интерфейс, который будет быстро загружаться, при этом не нужно будет тратить миллионы и годы на разработку решения.
Кому подойдет одностраничное приложение?
У одностраничных приложений есть свои плюсы и минусы. Поэтому при выборе типа разработки для MVP, нужно опираться на цели и KPI вашего стартапа. Прежде чем принять решение о создании SPA, мы рекомендуем определить, будет ли оно соответствовать вашим бизнес-потребностям.
Итак, каким компаниям нужно одностраничное приложение ? Вот наша подборка:
- Стартапам, которым нужна динамическая платформа с небольшим объемом данных. SPA часто используются для SaaS-платформ (software as service, «программное обеспечение как услуга»), социальных сетей и закрытых сообществ. Например, для таких решений, как приложения Google, Вконтакте, Netflix, Trello или Slack.
- Стартапам, для которых SEO — не ключевая метрика . Если для успешной реализации вашей идеи не нужна индексация поисковыми системами, то SPA — это оптимальный вариант.
- Стартапам с большими планами на будущее. Часть кода, который используется при разработке одностраничного приложения , мож но будет переиспользовать дальше. Это поможет сократить затраты и время на разработку на других платформах.
- Стартапам, у которых есть собственный API для создания приложений. Если у вас есть готовый к использованию API (интерфейс прикладного программирования), вы можете создать на его основе одностраничное приложение.
- Стартапам с фокусом на пользовательский опыт. Одностраничные приложения позволяют создать удобный и интуитивно понятный интерфейс, который привлекает внимание и вовлекает пользователей взаимодействовать с решением.
Подведем итоги
Сегодня одностраничные приложения повсюду, и мы пользуемся ими каждый день, не замечая этого. Крупные игроки на рынке приложений — например,Google, Netflix, Pinterest, Facebook и Airbnb, Вконтакте и даже Meduza — используют SPA.
Почему они выбирают одностраничные приложени я? Вот наш ответ: SPA работают быстро, не заставляют пользователей ждать и улучшают их опыт взаимодействия с решением. А скорость загрузки и удовлетворенность клиентов напрямую влияют на конверсию и прибыль.
С чего начать разработку?
Если вы только выбираете тип приложения, который подойдет для вашего MVP, спросите себя:
- Как будет выглядеть ваше решение?
- Сколько контента вы будете размещать?
- Как пользователи будут взаимодействовать с контентом на вашей странице?
- Какие преимущества получат пользователи от вашего приложения?
- Важна ли на данном этапе SEO-оптимизация вашего решения?
Одностраничные приложения лучше всего подходят для маркетплейсов, SaaS платформ, социальных сетей и тематических форумов.
Что дальше?
SPA подойдут далеко не всем стартапам. Но для тех, кому нужна динамичная и быстрая платформа с небольшими объемами данных, одностраничные приложения — отличный выбор.
Если вы решили приступить к реализации своей идеи и разработке MVP, ознакомьтесь с нашим руководством, чтобы узнать, где найти разработчика для своего одностраничного приложения и какие шаги предпринять дальше.
READ MORE Как построить стартап: краткий гайд от PurrwebВ Purrweb мы создаем MVP для стартапов с фокусом на UI/UX дизайне за 3-4 месяца. Над нашими проектами работает целая команда: разработчики, UX-дизайнеры и копирайтеры, QA инженеры и проджект-менеджеры.
Мы предлагаем полный цикл разработки и поддержки: от идеи до релиза, и работаем с разными вариантами разработки MVP, включая и одностраничные приложения.
Хотите узнать, подойдет ли вам одностраничное приложение? Заполните заявку сейчас и получите мнение наших экспертов.
Читайте также: