Продолжаем изучение Progressive Web Applications. После теоретической первой части и простого практического примера Hello Habr второй части попробуем перевести в PWA веб сайт на CMS Joomla.
Тип серверного фреймворка не важен. Задача данной статьи — показать перевод обычного сайта в PWA как концепцию, применимую к произвольным сайтам на любых фреймворках.
Для начала скачиваем и устанавливаем Joomla. При установке указываем, что необходимо наполнить сайт демо-данными — выбираем вариант «Блог». Получаем вот такой сайт — https://tetta.nut.cc/habr/hello-joomla/original/. Затем копируем все файлы сайта в каталог https://tetta.nut.cc/habr/hello-joomla/ — теперь у нас два работающих экземпляра сайта Joomla на одной базе данных. Первый мы оставим как есть, а второй будем переводить в PWA версию.
Исходный код примера этой статьи можно посмотреть на GitHub-e
Теперь нам нужно вычленить из сайта app shell — оболочку создаваемого приложения. При разработке PWA сайта «с нуля» для этого могут быть разные стратегии, но на готовом сайте удобно использовать деление на его статическую и динамическую части.
Статика — это то, что меняется редко и может быть частью app shell. Например, верхнее меню на нашем сайте можно считать статичным — оно меняется только администратором, и он может явно заказать обновление app shell на клиентских браузерах после его редактирования.
В тоже время сам контент, а также модули в position-7 и модуль Breadcrumbs в position-2, показывающий, где на сайте пользователь в данный момент находится, динамические. На браузер клиента они должны подгружаться.
Заменим все динамические блоки на placeholder-ы. В файле index.php шаблона меняем директивы:
Также подключаем в index.php в дополнение к скриптам шаблона наш javascript файл hello-joomla.js.
Создаем файл main-content.php со следующим содержимым:
Файл module-2.php:
И файл module-7.php:
Смысл сделанного в том, что при запросе https://tetta.nut.cc/habr/hello-joomla/index.php/5-your-modules?tmpl=module-7 мы будем получать только код модулей, находящихся в postion-7. То же самое с контентом.
Это все изменения в «серверной» части сайта. В других фреймворках данные операции (выделение app shell) проделать будет, возможно, чуть сложней, но здесь нам повезло.
В hello-joomla.js нам нужно реализовать динамическую подгрузку контента и модулей. Кроме того, нужно поменять поведение всех тэгов <A>, чтобы клик на ссылку инициировал динамическую загрузку данных страницы. Модули правой колонки будут грузиться один раз при открытии сайта в браузере, а breadcrumbs и контент — при каждом переходе по внутренней ссылке.
Это тоже несложно:
На данный момент мы переделали наш сайт в полноценное SPA — single page application — приложение. Осталась шлифовка — ссылка «Back to Top», стили верхнего меню, форма поиска, анимационный прелоадер и др.
Копия сайта в SPA режиме доступна по адресу https://tetta.nut.cc/habr/hello-joomla/spa/.
Подключаем в index.php манифест и sw.js из прошлого примера. Чтобы запретить Service Worker-у кэшировать динамические запросы, в hello-joomla.js в функции loadData к url добавляем «mode=nocache».
Всё. Можно закреплять на домашний экран.
Как видно, для того, чтобы превратить веб сайт в PWA приложение, не нужны никакие фреймворки и тулкиты. Всё делается руками, и код остается чистым и понятным.
В следующей статье мы, в форме полезных советов, функционально доведем сайт до уровня выпуска в продакшн. Остались стандартные SPA-шные доработки — заголовок страницы в браузере, Google Analitics, проверка, что для поисковиков ничего ценного не сбилось. Сделаем удобное управление кэшированием Service Worker-a для оперативного обновления элементов app shell. Кроме того, редакторы и комментаторы сайта хотят иметь возможность вставлять в материалы сайта картинки из интернета, в том числе по http протоколу.
Тип серверного фреймворка не важен. Задача данной статьи — показать перевод обычного сайта в PWA как концепцию, применимую к произвольным сайтам на любых фреймворках.
Для начала скачиваем и устанавливаем Joomla. При установке указываем, что необходимо наполнить сайт демо-данными — выбираем вариант «Блог». Получаем вот такой сайт — https://tetta.nut.cc/habr/hello-joomla/original/. Затем копируем все файлы сайта в каталог https://tetta.nut.cc/habr/hello-joomla/ — теперь у нас два работающих экземпляра сайта Joomla на одной базе данных. Первый мы оставим как есть, а второй будем переводить в PWA версию.
Исходный код примера этой статьи можно посмотреть на GitHub-e
Немного о строении Joomla
В Joomla есть понятие шаблона — это набор веб ресурсов, отвечающих за презентационный уровень. Шаблоны расположены в директории /templates, наш стандартный «из коробки» называется protostar.
В общем случае после получения браузерного запроса Joomla запускает движок, делает свои дела, а затем передает исполнение запроса в /templates/protostar/index.php, который уже генерит HTML клиенту. Данный файл представляет из себя простой PHP файл, в котором дополнительно возможно использование двух директив:
<jdoc:include type="component" /> <jdoc:include type="modules" name="position-id" style="..." />
Первая вставляет вместо себя основной материал, соответствующий запрошенному URL (компонент), вторая — модули, прописанные администратором для указанной позиции. Любая страница в Joomla состоит из компонента и модулей.
Если посмотреть на шаблон сайта, то видно блок основного материала в центральной части страницы, и модули вокруг нет. Верхнее меню — position-1, правая колонка с двумя модулями «Older Posts» и «Most Read Posts» — position-7 и так далее.
У Joomla есть особенность — если в пришедшем GET запросе есть параметр tmpl с каким-нибудь значением somePage, тo Joomla передает исполнение запроса не index.php файлу шаблона, а somePage.php, если он есть. Мы используем это ниже.
Application shell
Теперь нам нужно вычленить из сайта app shell — оболочку создаваемого приложения. При разработке PWA сайта «с нуля» для этого могут быть разные стратегии, но на готовом сайте удобно использовать деление на его статическую и динамическую части.
Статика — это то, что меняется редко и может быть частью app shell. Например, верхнее меню на нашем сайте можно считать статичным — оно меняется только администратором, и он может явно заказать обновление app shell на клиентских браузерах после его редактирования.
В тоже время сам контент, а также модули в position-7 и модуль Breadcrumbs в position-2, показывающий, где на сайте пользователь в данный момент находится, динамические. На браузер клиента они должны подгружаться.
1. Изменения на сервере
Заменим все динамические блоки на placeholder-ы. В файле index.php шаблона меняем директивы:
<jdoc:include type="component" />
на
<div id="main-content"></div>
<jdoc:include type="modules" name="position-id" style="..." />
на
<div id="module-id"></div>
Также подключаем в index.php в дополнение к скриптам шаблона наш javascript файл hello-joomla.js.
Создаем файл main-content.php со следующим содержимым:
<jdoc:include type="component" />
Файл module-2.php:
<jdoc:include type="modules" name="position-2" style="none" />
И файл module-7.php:
<jdoc:include type="modules" name="position-7" style="well" />
Смысл сделанного в том, что при запросе https://tetta.nut.cc/habr/hello-joomla/index.php/5-your-modules?tmpl=module-7 мы будем получать только код модулей, находящихся в postion-7. То же самое с контентом.
Это все изменения в «серверной» части сайта. В других фреймворках данные операции (выделение app shell) проделать будет, возможно, чуть сложней, но здесь нам повезло.
2. Клиентская часть
В hello-joomla.js нам нужно реализовать динамическую подгрузку контента и модулей. Кроме того, нужно поменять поведение всех тэгов <A>, чтобы клик на ссылку инициировал динамическую загрузку данных страницы. Модули правой колонки будут грузиться один раз при открытии сайта в браузере, а breadcrumbs и контент — при каждом переходе по внутренней ссылке.
Это тоже несложно:
hello-joomla.js
// Загружает содержимое url в HTML элемент el
function loadData(el, url){
url.indexOf("?") >= 0 ? url += "&" : url += "?";
url = url + 'mode=nocache&tmpl=' + el;
fetch(url)
.then(
function(response) {
if (response.status == 200) {
response.text().then(function(data) {
document.getElementById(el).innerHTML = data;
});
}
})
.catch();
return false;
}
// Вешает на все <a> кастомный обработчик кликов
function handleLinks() {
var links = document.querySelectorAll('a');
for (var i = 0; i < links.length; ++i) {
links[i].removeEventListener("click", handleLink);
links[i].addEventListener("click", handleLink);
}
}
// Обработчик кликов
function handleLink(e) {
e.preventDefault();
loadData("main-content", this.href);
loadData("module-2", this.href);
handleLinks();
return false;
}
// Первоначальная загрузка страницы в браузере
function DOMLoaded() {
loadData("main-content", location.pathname);
loadData("module-2", location.pathname);
loadData("module-7", location.pathname);
handleLinks();
}
document.addEventListener('DOMContentLoaded', DOMLoaded, true);
На данный момент мы переделали наш сайт в полноценное SPA — single page application — приложение. Осталась шлифовка — ссылка «Back to Top», стили верхнего меню, форма поиска, анимационный прелоадер и др.
Копия сайта в SPA режиме доступна по адресу https://tetta.nut.cc/habr/hello-joomla/spa/.
3. SPA -> PWA
Подключаем в index.php манифест и sw.js из прошлого примера. Чтобы запретить Service Worker-у кэшировать динамические запросы, в hello-joomla.js в функции loadData к url добавляем «mode=nocache».
Всё. Можно закреплять на домашний экран.
Выводы
Как видно, для того, чтобы превратить веб сайт в PWA приложение, не нужны никакие фреймворки и тулкиты. Всё делается руками, и код остается чистым и понятным.
В следующей статье мы, в форме полезных советов, функционально доведем сайт до уровня выпуска в продакшн. Остались стандартные SPA-шные доработки — заголовок страницы в браузере, Google Analitics, проверка, что для поисковиков ничего ценного не сбилось. Сделаем удобное управление кэшированием Service Worker-a для оперативного обновления элементов app shell. Кроме того, редакторы и комментаторы сайта хотят иметь возможность вставлять в материалы сайта картинки из интернета, в том числе по http протоколу.
Одним из замечательных свойств концепции PWA является то, что она возвращает к жизни давно потерянную в многочисленных серверных и браузерных фреймворках парадигму MVC. «View» теперь живет на клиенте, и на сервер браузер обращается за данными, а не за их представлением.
И, в отличие от обычных SPA, PWA строит это «View» не тяжелыми javascript фреймворками, а старым добрым быстрым и понятным html+css.
bosom
2018 год, статья о Joomla! Не верю глазам своим! Серьёзно?
kub2
Статья о Joomla? Серьёзно?