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

    Продолжаем изучение 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.
    Поделиться публикацией

    Похожие публикации

    Комментарии 3
      +2

      2018 год, статья о Joomla! Не верю глазам своим! Серьёзно?

        +2
        Статья о Joomla? Серьёзно?
        0
        А что не так с Joomla? Про Wordpress пишут тут чаще хотя эта CMS уж точно ничем не лучше, мягко говоря…
        В других статьях по PWA в примерах я вижу часто папку с набором логотипов в png, разных размеров, странно почему бы не использовать один в svg?

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое