MicroSPA, или как изобрести квадратное колесо

от автора

Всем привет, меня зовут Андрей Яковенко, и я веб-разработчик компании Digital Design.

В нашей компании есть множество проектов, реализованных с помощью системы управления веб-контентом sitefinity, или по-простому CMS. Причины, по которым мы ее используем, были описаны ранее в этой статье. CMS – это, как правило, Multi Page Application, и сегодня я расскажу о том, что может дать внедрение frontend-фреймворков в решения на sitefinity и как это сделать.


Лирическое отступление

Хоть sitefinity и имеет на борту Angular.js, возможность интеграции других фреймворков отсутствует в силу закрытости исходных кодов. Однако это не мешает нам использовать возможности других фреймворков.

Примеры в данной статье не являются панацеей и несут в основном информационный характер.

Поиск нового

Так как Angular, хоть и первой версии, уже присутствует в sitefinity, нам захотелось подружить нашу CMS с React или Vue.js.

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

После беглого просмотра возможных решений был найден интересный проект, который компилировал страницы, написанные на React, в статический html. Такое решение нам не подходило, так как нам необходимо не терять всех прелестей SSR (Server Side Render) наряду с использованием исполняемого кода на стороне клиента.

От слов к делу

Sitefinity, как и большинство CMS, позволяет компоновать страницу различными элементами для отображения контента (виджетами). Мы на примере рассмотрим варианты внедрения Vue.js в уже готовые виджеты.

Первый способ (простой)

Данный способ заключается в подключении Vue.js как библиотеки в основной шаблон страницы.

После этого мы в любом месте можем инициализировать наше приложение в любом виджете.

Пример простого виджета:

new Vue({     el: '#widget-id',     data: {         msg: 'Hello world',     }, }) 

Однако это будет означать, что весь блок виджета будет использован как шаблон, и Vue.js будет пытаться его интерполировать и, чтобы вывести сообщение в нужном месте, необходимо будет написать специальную конструкцию, которая будет отображаться, если что-то вызовет приостановку выполнения js кода перед рендером, или если у пользователя будет отключен JavaScript.

Решением данной проблемы будет написание собственного шаблона, который будет дублировать виджет. Расширим наш компонент.

Пример:

new Vue({     el: '#widget-id',     data: {         msg: 'Hello world',     },     template: '<div>{{msg}}</div>', }) 

Теперь весь html код нашего виджета будет заменен на шаблон, описанный в поле template, а для того чтобы передать данные из модели виджета во Vue, достаточно конвертировать модель в JSON любым удобным способом и передать его в поле data.

Второй способ (сложный)

Для данного способа нам потребуется webpack, в минимальной конфигурации которого будет vue-loader. Также у нас нет необходимости в использовании html-extract-plugin, т.к. мы можем хранить шаблоны в js коде.

Теперь мы можем использовать однофайловые компоненты Vue.

Пример однофайлового компонента (Sample.vue):

<template>     <div>{{msg}}</div> </template>  <script> export default {     name: 'Sample',     data: function () {         return {             msg: 'Hello world',         }     }, } </script> 

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

После написания компонента-виджета нам необходимо его инициализировать.

Пример инициализации виджета:

import Vue from 'vue' import Sample from '../Sample.vue'  Vue({     render: function (h) {         return h(Sample)     } }).$mount('#widget-id') 

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

Расширим наш пример:

import Vue from 'vue' import Sample from '../Sample.vue'  (function () {     Vue({         render: function (h) {             return h(Sample)         }     }).$mount('#widget-id') })() 

Осталось передать данные модели виджета во Vue.js компонент. Это легко сделать, записав их в JSON перед передачей в объект data экземпляра Vue, после чего их можно передать компоненту в качестве пропсов.

Пример:

import Vue from 'vue' import Sample from '../Sample.vue'  (function () {     Vue({         data: function () {             return {                 some: 'some value',             }         },         render: function (h) {             return h(Sample, { props: data })         }     }).$mount('#widget-id') })() 

Небольшое ревью

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

Однако у обоих способов есть один большой недостаток – при таком использовании фреймворков появляется необходимость дважды выполнять одну и ту же работу для участков страниц, от которых зависит SEO.

С другой стороны, при желании, с помощью такого подхода можно подключить любой фреймворк, библиотеку или написать собственный DOM-менеджер на ванильном JavaScript или jQuery.

На этом все. Спасибо за внимание.

ссылка на оригинал статьи https://habr.com/ru/company/digdes/blog/483988/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *