Одностраничное приложение - Single-page application

А одностраничное приложение (СПА) это веб приложение или же интернет сайт который взаимодействует с пользователем, динамически перезаписывая текущий страница в Интернете с новыми данными из веб сервер вместо стандартного метода загрузки браузером всех новых страниц. Цель - более быстрые переходы, которые делают сайт Чувствовать больше похоже на родное приложение.

В СПА все необходимое HTML, JavaScript, и CSS код либо извлекается браузером при загрузке одной страницы,[1] или соответствующие ресурсы динамически загружаются и добавляются на страницу по мере необходимости, обычно в ответ на действия пользователя. Страница не перезагружается ни на каком этапе процесса и не передает управление другой странице, хотя хэш местоположения или API истории HTML5 можно использовать для обеспечения восприятия и навигации по отдельным логическим страницам в приложении.[2]

История

Происхождение термина одностраничное приложение неясны, хотя концепция обсуждалась как минимум еще в 2003 году.[3] Стюарт Моррис, студент-программист в Кардиффском университете, Уэльс, в апреле 2002 года написал автономный веб-сайт slashdotslash.com с теми же целями и функциями.[4] а позже в том же году Лукас Бирдо, Кевин Хакман, Майкл Пичи и Клиффорд Йе описали реализацию одностраничной заявки в патенте США 8,136,109.[5]

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

Технические подходы

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

Фреймворки JavaScript

Фреймворки и библиотеки JavaScript веб-браузера, такие как AngularJS, Ember.js, ExtJS, Knockout.js, Meteor.js, Реагировать, Vue.js, и Svelte приняли принципы SPA. Помимо ExtJS, все это Открытый исходный код.

  • AngularJS полностью клиентский фреймворк. Шаблоны AngularJS основаны на двунаправленном Привязка данных пользовательского интерфейса. Привязка данных - это автоматический способ обновления представления при изменении модели, а также обновления модели при изменении представления. HTML-шаблон компилируется в браузере. На этапе компиляции создается чистый HTML-код, который браузер повторно отображает в режиме реального времени. Этот шаг повторяется для последующих просмотров страницы. В традиционном программировании HTML на стороне сервера такие концепции, как контроллер и модель, взаимодействуют внутри серверного процесса для создания новых представлений HTML. В структуре AngularJS состояние контроллера и модели поддерживается в клиентском браузере. Следовательно, новые страницы могут быть созданы без какого-либо взаимодействия с сервером.
  • Ember.js это клиентская платформа веб-приложений JavaScript, основанная на модель – представление – контроллер (MVC) программный архитектурный шаблон. Он позволяет разработчикам создавать масштабируемые одностраничные приложения путем включения общих идиом и передовых методов в структуру, которая предоставляет богатую объектную модель, декларативную двустороннюю привязку данных, вычисляемые свойства, автоматически обновляемые шаблоны на основе Handlebars.js и маршрутизатор для управление состоянием приложения.
  • ExtJS также является фреймворком на стороне клиента, который позволяет создавать приложения MVC. Он имеет собственную систему событий, управление окнами и компоновкой, управление состоянием (хранилища) и различные компоненты пользовательского интерфейса (сетки, диалоговые окна, элементы форм и т. Д.). У него есть собственная система классов с динамическим или статическим загрузчиком. Приложение, созданное с помощью ExtJS, может существовать само по себе (с состоянием в браузере) или с сервером (например, с ОТДЫХ API, который используется для наполнения его внутренних хранилищ). ExtJS имеет только встроенные возможности для использования localStorage, поэтому более крупным приложениям требуется сервер для хранения состояния.
  • Knockout.js это фреймворк на стороне клиента, который использует шаблоны на основе Модель-представление-ViewModel шаблон.
  • Meteor.js - это полнофункциональная (клиент-серверная) платформа JavaScript, разработанная исключительно для SPA. Он имеет более простую привязку данных, чем Angular, Ember или ReactJS,[6] и использует Распределенный протокол данных[7] и шаблон публикации – подписки для автоматического распространения изменений данных на клиентов в режиме реального времени, не требуя от разработчика написания кода синхронизации. Реактивность полного стека гарантирует, что все слои, от базы данных до шаблонов, обновляются автоматически при необходимости. Экосистемные пакеты, такие как Рендеринг на стороне сервера[8] решить проблему поисковой оптимизации.
  • Реагировать это Библиотека JavaScript для строительства пользовательские интерфейсы. Он поддерживается Facebook, Instagram и сообщество индивидуальных разработчиков и корпораций. React использует новый язык, который представляет собой смесь JS и HTML (подмножество HTML). Несколько компаний используют React с Redux (библиотека JavaScript) который добавляет возможности управления состоянием, которые (вместе с несколькими другими библиотеками) позволяют разработчикам создавать сложные приложения.[9]
  • Vue.js это платформа JavaScript для создания пользовательских интерфейсов. Разработчики Vue также предоставляют Vuex для управления состоянием.
  • Svelte - это структура для создания пользовательских интерфейсов, которая компилирует код Svelte для манипуляций с DOM JavaScript, избегая необходимости связывать платформу с клиентом и позволяя упростить синтаксис разработки приложений.

Аякс

По состоянию на 2006 год наиболее известной использованной техникой была Аякс.[1] Ajax предполагает использование асинхронных запросов к серверу для XML или же JSON данные, например, с помощью JavaScript XMLHttpRequest или более современный fetch () (с 2017 г.) или устаревший Объект ActiveX. В отличие от декларативный подход большинства фреймворков SPA, с Ajax веб-сайт напрямую использует JavaScript или библиотеку JavaScript, такую ​​как jQuery манипулировать ДОМ и редактировать элементы HTML. Ajax получил дальнейшую популяризацию благодаря таким библиотекам, как jQuery, который обеспечивает более простой синтаксис и нормализует поведение Ajax в разных браузерах, которые исторически имели разное поведение.

WebSockets

WebSockets - это технология двунаправленной связи клиент-сервер в реальном времени, которая является частью спецификации HTML5. Для связи в реальном времени их использование превосходит Ajax с точки зрения производительности.[10] и простота.

Отправленные сервером события

Отправленные сервером события (SSE) - это метод, с помощью которого серверы могут инициировать передачу данных клиентам браузера. После того, как начальное соединение установлено, поток событий остается открытым, пока не будет закрыт клиентом. SSE отправляются по традиционному протоколу HTTP и имеют множество функций, которые отсутствуют в WebSockets по своей конструкции, например автоматическое переподключение, идентификаторы событий и возможность отправлять произвольные события.[11]

Плагины браузера

Хотя этот метод устарел, асинхронные вызовы сервера также могут быть выполнены с использованием технологий подключаемых модулей браузера, таких как Silverlight, Вспышка, или же Java-апплеты.

Транспорт данных (XML, JSON и Ajax)

Запросы к серверу обычно приводят к необработанным данным (например, XML или же JSON ) или новый HTML возвращаются. В случае, когда сервер возвращает HTML, JavaScript на клиенте обновляет частичную область DOM (Объектная модель документа ).[12] Когда возвращаются необработанные данные, часто клиентский JavaScript XML / (XSL ) процесс (а в случае JSON a шаблон ) используется для преобразования необработанных данных в HTML, который затем используется для обновления частичной области DOM.

Архитектура сервера

Архитектура тонкого сервера

SPA перемещает логику с сервера на клиент, при этом роль веб-сервера превращается в API чистых данных или веб-службу. Этот архитектурный сдвиг в некоторых кругах был назван «архитектурой тонкого сервера», чтобы подчеркнуть, что сложность была перенесена с сервера на клиент, с аргументом, что это в конечном итоге снижает общую сложность системы.

Толстая архитектура сервера с отслеживанием состояния

Сервер хранит необходимое состояние в памяти о состоянии клиента страницы. Таким образом, когда любой запрос попадает на сервер (обычно это действия пользователя), сервер отправляет соответствующий HTML и / или JavaScript с конкретными изменениями, чтобы привести клиента в новое желаемое состояние (обычно добавление / удаление / обновление части клиентский DOM). В то же время состояние на сервере обновляется. Большая часть логики выполняется на сервере, и HTML обычно также отображается на сервере. В некотором смысле сервер имитирует веб-браузер, принимает события и выполняет дельта-изменения в состоянии сервера, которые автоматически передаются клиенту.

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

Толстая архитектура сервера без сохранения состояния

Это вариант подхода к серверу с отслеживанием состояния. Клиентская страница отправляет данные, представляющие ее текущее состояние, на сервер, обычно через запросы Ajax. Используя эти данные, сервер может восстановить состояние клиента той части страницы, которую необходимо изменить, и может сгенерировать необходимые данные или код (например, в формате JSON или JavaScript), который возвращается клиенту для получения его в новое состояние, обычно изменяя дерево DOM страницы в соответствии с действием клиента, которое мотивировало запрос.

Этот подход требует, чтобы на сервер было отправлено больше данных, и может потребоваться больше вычислительных ресурсов на запрос для частичного или полного восстановления состояния клиентской страницы на сервере. В то же время этот подход легче масштабировать, поскольку на сервере нет данных о странице для каждого клиента, и, следовательно, запросы Ajax могут быть отправлены на разные серверные узлы без необходимости совместного использования данных сеанса или привязки к серверу.

Работает локально

Некоторые СПА могут выполняться из локального файла с помощью схема URI файла. Это дает пользователям возможность загружать SPA с сервера и запускать файл с локального запоминающего устройства, независимо от возможности подключения к серверу. Если такой SPA хочет хранить и обновлять данные, он должен использовать браузер на основе Веб-хранилище. Эти приложения извлекают выгоду из достижений, доступных с HTML5.[13]

Проблемы с моделью SPA

Поскольку SPA представляет собой эволюцию от модели перерисовки страниц без сохранения состояния, для которой изначально были разработаны браузеры, возникли некоторые новые проблемы. Возможные решения (различной сложности, полноты и авторского контроля) включают:[14]

  • Клиентские библиотеки JavaScript.
  • Серверные веб-фреймворки, специализирующиеся на модели SPA.[15][16][17]
  • Эволюция браузеров и спецификация HTML5,[18] разработан для модели SPA.

Поисковая оптимизация

Из-за отсутствия выполнения JavaScript на сканерах некоторых популярных Поисковые системы,[19] SEO (Поисковая оптимизация ) исторически представлял проблему для общедоступных веб-сайтов, желающих принять модель SPA.[20]

В период с 2009 по 2015 гг. Центр веб-мастеров Google предложил, а затем рекомендовал "схему сканирования AJAX"[21][22] использование начального восклицательного знака в идентификаторах фрагментов для сохранения состояния AJAX страницы (#!). На сайте SPA должно быть реализовано специальное поведение, чтобы сканер поисковой системы мог извлекать соответствующие метаданные. Для поисковых систем, которые не поддерживают эту схему хеширования URL-адресов, хешированные URL-адреса SPA остаются невидимыми. Эти «хэш-бэнг» URI считались проблематичными рядом авторов, включая Джени Теннисон из W3C, потому что они делают страницы недоступными для тех, у кого нет JavaScript активирован в их браузере. Они тоже ломаются HTTP-реферер заголовки, поскольку браузеры не могут отправлять идентификатор фрагмента в заголовке Referer.[23] В 2015 году Google отказался от своего предложения по сканированию с помощью hash-bang AJAX.[24]

В качестве альтернативы приложения могут отображать загрузку первой страницы на сервере и последующие обновления страницы на клиенте. Это традиционно сложно, потому что код рендеринга может быть написан на другом языке или на другом фреймворке на сервере и на клиенте. Использование шаблонов без логики, кросс-компиляция с одного языка на другой или использование одного и того же языка на сервере и клиенте может помочь увеличить объем кода, который можно совместно использовать.

Поскольку совместимость с SEO для SPA нетривиальна, стоит отметить, что SPA обычно не используются в контексте, когда индексация поисковой системы является обязательной или желательной. Примеры использования включают приложения, которые отображают личные данные, скрытые за аутентификация система. В случаях, когда эти приложения являются потребительскими продуктами, часто используется классическая модель «перерисовки страницы» для целевой страницы приложения и маркетингового сайта, которая предоставляет достаточно метаданных для того, чтобы приложение появилось в качестве попадания в запросе поисковой системы. Блоги, форумы поддержки и другие традиционные артефакты перерисовки страниц часто располагаются вокруг SPA, которые могут заполнять поисковые системы соответствующими терминами.

Другой подход, используемый серверно-ориентированными веб-фреймворками, такими как Java-based ItsNat заключается в отображении любого гипертекста на сервере с использованием того же языка и технологии шаблонов. В этом подходе сервер точно знает состояние DOM на клиенте, любое необходимое обновление большой или малой страницы генерируется на сервере и передается Ajax, точный код JavaScript для перевода клиентской страницы в новое состояние, выполняя методы DOM. . Разработчики могут решить, какие состояния страницы должны сканироваться веб-пауками для SEO, и иметь возможность генерировать необходимое состояние во время загрузки, генерируя простой HTML вместо JavaScript. В случае инфраструктуры ItsNat это происходит автоматически, поскольку ItsNat хранит дерево DOM клиента на сервере как дерево DOM Java W3C; рендеринг этого дерева DOM на сервере генерирует простой HTML во время загрузки и действия DOM JavaScript для запросов Ajax. Эта двойственность очень важна для SEO, потому что разработчики могут создавать с одним и тем же кодом Java и чистым шаблоном на основе HTML, создавая желаемое состояние DOM на сервере; во время загрузки страницы ItsNat генерирует обычный HTML, что делает это состояние DOM SEO-совместимым.

Начиная с версии 1.3,[25] ItsNat предоставляет новый режим без сохранения состояния, и клиентская DOM не хранится на сервере, потому что с клиентом в режиме без сохранения состояния состояние DOM частично или полностью реконструируется на сервере при обработке любого запроса Ajax на основе необходимых данных, отправленных клиентом, информируя сервер текущего состояния DOM; режим без сохранения состояния может быть также совместим с SEO, поскольку совместимость с SEO происходит во время загрузки начальной страницы, на которую не влияют режимы с сохранением состояния или без состояния. Другой возможный выбор - такие фреймворки, как PreRender, Puppeteer, Rendertron, которые можно легко интегрировать в любой веб-сайт в качестве промежуточного программного обеспечения с конфигурацией веб-сервера, позволяющей обрабатывать запросы ботов (бот Google и другие) промежуточным программным обеспечением, в то время как запросы, не относящиеся к ботам, обслуживаются как обычно . Эти фреймворки периодически кэшируют соответствующие страницы веб-сайтов, чтобы последние версии были доступны поисковым системам. Эти фреймворки официально одобрены Google.[26]

Есть несколько обходных путей, чтобы создать впечатление, что веб-сайт доступен для сканирования. Оба включают создание отдельных HTML-страниц, которые отражают содержимое SPA. Сервер может создать версию сайта на основе HTML и доставить ее сканерам, или можно использовать автономный браузер, такой как PhantomJS для запуска приложения JavaScript и вывода полученного HTML.

И то, и другое требует значительных усилий и в конечном итоге может вызвать головную боль при обслуживании больших сложных сайтов. Есть также потенциальные подводные камни SEO. Если HTML-код, сгенерированный сервером, будет слишком отличаться от содержимого SPA, сайт будет оштрафован. Запуск PhantomJS для вывода HTML может замедлить скорость отклика страниц, для чего поисковые системы, в частности Google, понижают рейтинг.[27]

Разделение клиент-серверного кода

Один из способов увеличить объем кода, который может совместно использоваться между серверами и клиентами, - это использовать язык шаблонов без логики, например Усы или же Рули. Такие шаблоны могут отображаться на разных языках хоста, например Рубин на сервере и JavaScript в клиенте. Однако простой обмен шаблонами обычно требует дублирования бизнес-логика используется для выбора правильных шаблонов и заполнения их данными. Отрисовка из шаблонов может иметь отрицательное влияние на производительность при обновлении только небольшой части страницы, например значения вводимого текста в большом шаблоне. Замена всего шаблона также может нарушить выбор пользователя или положение курсора, тогда как обновление только измененного значения может не измениться. Чтобы избежать этих проблем, приложения могут использовать Привязки данных пользовательского интерфейса или гранулированный ДОМ манипуляции для обновления только соответствующих частей страницы вместо повторного рендеринга целых шаблонов.

История браузера

Поскольку SPA по определению является «отдельной страницей», модель нарушает дизайн браузера для навигации по истории страниц с использованием кнопок «вперед» или «назад». Это представляет собой препятствие для удобства использования, когда пользователь нажимает кнопку возврата, ожидая предыдущего состояния экрана в SPA, но вместо этого выгружается отдельная страница приложения и отображается предыдущая страница в истории браузера.

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

Для дальнейшего решения этой проблемы спецификация HTML5 представила pushState и replaceState обеспечение программного доступа к актуальному URL-адресу и истории браузера.

Аналитика

Инструменты аналитики, такие как Гугл Аналитика в значительной степени полагаются на загрузку целых новых страниц в браузере, инициированную загрузкой новой страницы. СПА так не работают.

После загрузки первой страницы все последующие изменения страницы и содержимого обрабатываются внутри приложения, которое должно просто вызвать функцию для обновления пакета аналитики. Без вызова указанной функции браузер никогда не запускает новую загрузку страницы, ничего не добавляется в историю браузера, а пакет аналитики не знает, кто что делает на сайте.

Добавление загрузки страницы в SPA

Можно добавить события загрузки страницы в SPA с помощью API истории HTML5; это поможет интегрировать аналитику. Сложность заключается в управлении этим и обеспечении точного отслеживания всего - это включает в себя проверку отсутствующих отчетов и двойных записей. Некоторые фреймворки обеспечивают интеграцию аналитики с открытым исходным кодом, адресованную большинству основных поставщиков аналитики. Разработчики могут интегрировать их в приложение и убедиться, что все работает правильно, но нет необходимости делать все с нуля.[27]

Скорость начальной загрузки

Одностраничные приложения имеют более медленную загрузку первой страницы, чем серверные приложения. Это связано с тем, что первая загрузка должна привести к отключению платформы и кода приложения перед рендерингом требуемого представления в виде HTML в браузере. Серверное приложение просто должно отправить в браузер необходимый HTML-код, уменьшая задержку и время загрузки.

Ускорение загрузки страницы

Есть несколько способов ускорить начальную загрузку SPA, например усиленный подход к кешированию и отложенная загрузка модулей при необходимости. Но невозможно уйти от того факта, что ему необходимо загрузить фреймворк, по крайней мере, часть кода приложения, и, скорее всего, он обратится к API для данных перед отображением чего-либо в браузере.[27] Это компромиссный сценарий «заплати мне сейчас или заплати позже». Вопрос производительности и времени ожидания остается решением, которое должен принять разработчик.

Жизненный цикл страницы

SPA полностью загружается при начальной загрузке страницы, а затем области страницы заменяются или обновляются новыми фрагментами страницы, загружаемыми с сервера по запросу. Чтобы избежать чрезмерной загрузки неиспользуемых функций, SPA часто будет постепенно загружать больше функций по мере необходимости, либо небольшие фрагменты страницы, либо полные модули экрана.

Таким образом, существует аналогия между «состояниями» в SPA и «страницами» на традиционном веб-сайте. Поскольку «навигация по состояниям» на той же странице аналогична навигации по страницам, теоретически любой страничный веб-сайт может быть преобразован в одностраничный, заменяя на той же странице только измененные части.

Подход SPA в Интернете аналогичен однодокументный интерфейс (SDI) метод представления, популярный в нативных настольных приложениях.

Рекомендации

  1. ^ а б Фланаган, Дэвид "JavaScript - полное руководство ", 5 изд., О'Рейли, Севастополь, Калифорния, 2006 г., стр.497
  2. ^ «Исправление кнопки« Назад »: поведение SPA с использованием хеша местоположения». Блог Falafel Software. Получено 18 января, 2016.
  3. ^ «Внутренний просмотр: расширение парадигмы просмотра веб-страниц». Получено 3 февраля, 2011.
  4. ^ "Slashdotslash.com: автономный веб-сайт, использующий DHTML". Получено 6 июля, 2012.
  5. ^ «Патент США 8,136,109». Получено 12 апреля, 2002.
  6. ^ "Пламя метеора". Meteor Blaze - мощная библиотека для создания пользовательских интерфейсов, обновляемых в реальном времени. Blaze выполняет те же функции, что и Angular, Backbone, Ember, React, Polymer или Knockout, но его гораздо проще использовать. Мы создали его, потому что думали, что другие библиотеки делают программирование пользовательского интерфейса излишне сложным и запутанным.
  7. ^ Представляем DDP, 21 марта 2012 г.
  8. ^ «Рендеринг на стороне сервера для Meteor». Архивировано из оригинал 20 марта 2015 г.. Получено 31 января, 2015.
  9. ^ «Одностраничные приложения против многостраничных приложений: плюсы, минусы, подводные камни - BLAKIT - IT Solutions». blak-it.com. БЛАКИТ - ИТ-решения. 17 октября 2017 г.. Получено 19 октября, 2017.
  10. ^ «Мониторинг в реальном времени с использованием AJAX и WebSockets». www.computer.org. Получено 1 июня, 2016.
  11. ^ «События, отправленные сервером». W3C. 17 июля 2013 г.
  12. ^ «Использование InnerHTML». www.webrocketx.com. Получено 21 января, 2016.
  13. ^ «Неопубликованные веб-приложения».
  14. ^ "Манифест одностраничного интерфейса". Получено 25 апреля, 2014.
  15. ^ "Дерби". Получено 11 декабря, 2011.
  16. ^ "Sails.js". Получено 20 февраля, 2013.
  17. ^ «Учебное пособие: веб-сайт с одностраничным интерфейсом и ItsNat». Получено 13 января, 2011.
  18. ^ HTML5
  19. ^ "Что видит пользователь, что видит сканер". Получено 6 января, 2014. браузер может выполнять JavaScript и создавать контент на лету - сканер не может
  20. ^ «Сделать приложения Ajax доступными для сканирования». Получено 6 января, 2014. Исторически сложилось так, что поисковым системам было сложно обрабатывать приложения Ajax, поскольку создается контент Ajax.
  21. ^ «Предложение сделать AJAX доступным для сканирования». Google. 7 октября 2009 г.. Получено 13 июля, 2011.
  22. ^ "(Технические характеристики) Обеспечение возможности сканирования приложений AJAX". Google. Получено 4 марта, 2013.
  23. ^ "URI хэша". Блог W3C. 12 мая 2011 г.. Получено 13 июля, 2011.
  24. ^ «Прекращение поддержки нашей схемы сканирования AJAX». Официальный блог Центра веб-мастеров Google. Получено 23 февраля, 2017.
  25. ^ «Примечания к выпуску ItsNat v1.3». Получено 9 июня, 2013.
  26. ^ https://developers.google.com/search/docs/guides/dynamic-rendering
  27. ^ а б c Холмс, Симона (2015). Получение MEAN с помощью Mongo, Express, Angular и Node. Публикации Мэннинга. ISBN  978-1-6172-9203-3

внешняя ссылка