Pull to refresh

PWA — это просто. Hello Joomla

Reading time 5 min
Views 7.5K
Продолжаем изучение 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

Немного о строении 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 и так далее.

image

У 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.
Tags:
Hubs:
+5
Comments 3
Comments Comments 3

Articles