Небольшое, но удобное решения для использования Vue.js в bitrix. Решение не подразумевает сборку вообще и подходит для маленьких и средних проектов, и уже показало свою стабильность в продакшн много раз.
Но если вам нужно что-то более специфическое и гибкое, то конечно vue-cli, webpack или bitrix/cli подходит больше, я сам периодически употребляю. Эта статья совсем про другое.
В своём решении я поставил несколько требований:
Компоненты в template.vue файлах, как уже привык с vue-cli;
Простота подключения компонентов;
Автоматическое подключение зависимостей;
Переиспользуемость компонентов между проектами;
Привычное для bitrix-разработчика поведение.
Вызов и дальнейшие действия, очень похожи на уже привычное подключение битриксовых компонентов:
<?php
Dbogdanoff\Bitrix\Vue::includeComponent(['todo-list']);
?>
<div id="app">
<todo-list></todo-list>
</div>
<sc ript>
var mainVueApp = new Vue({
el: '#app'
})
</sc ript>
Шаблон компонента будет подключен после вызова Vue::includeComponent:
Скрипт компонента можно вынести в script.js и положить в папку компонента, он будут подключен автоматически, так же как в обычных компонентах bitrix. То же самое относится и к стиля, их можно поместить в файле style.css.
Ни одни из файлов не является обязательным, таким образом весь компонент может быть описан в одном script.js файле или в одном template.vue файле, но в них обязательно должна присутствовать регистрация компонента пример.
По умолчанию поиск компонентов производится в папке /local/components-vue. Данное поведение можно изменить, объявив константу:
define('DBOGDANOFF_VUE_PATH', '/components-vue'); // поменяли на корень сайта в /components-vue
Богданов Денис, а мы в своих проектах встроили PHP-minify и PHP-less. JS/CSS миницифируются во время хита (в дальнейшем идёт просто проверка даты изменения основного и min-файла - нагрузка минимальна).LESS по такому же принципу компиляца.
По подключению script.js компонента vue - я думаю сделать автоматическую вставку template.vue в сам script.js например в момент создания min версии.
А как реализовать в данном варианте обмен по глобальной шине между двумя приложениями? в рамках одной открытой вкладки все работает, но по заявлению разработчиков битрикс позволяет по глобальной шине производить обмен между приложениями на разных страницах. Есть решение? Либо онли пуш или сокеты?
Богданов Денис, прикольное решение. У меня вопрос: в репозитории проекта с примерами использования есть такие компоненты как 'dbogdanoff-loader' и 'dbogdanoff-popup', как их использовать? Смотрел код: loader должен заменять стандартный некрасивый битриксовый ajax-прелоадер? Планируете ли доработать пример, чтобы было сразу наглядно видно на одной странице, что есть лоадер и есть всплавающее окно?
Представим, что нам надо отправлять сообщения в Битрикс24 на события из bitbucket, например Тимлиду ссылку на пулреквест для кодревью.
Bitbucket webhook Вебхуки bitbucket имеют события на пулреквесты, пуши и ишью. Полный перечень тут. Добавляется вебхука в настройках репозитория:
Укажите путь, куда будет отправлен запрос и выберите какие события вы хотите обрабатывать:
Обработка событий и отправка сообщения в чат Следующий скрипт, принимает запрос от bitbucket и отправляет ссылку на пулреквест Тимлиду на портал. Отправленное сообщение состоит из названия и ссылки на пулреквест.
Вот так просто. Логику поиска получателей или отправителей вы уже должны реализовать самостоятельно, в зависимости от ваших процессов и замысла. В нашем примере, для упрощения, ID пользователей прописаны явно.
Для обработки вебхуков bitbucket используется библиотека. Библиотека понимает большинство событий и комплектует объекты данными ответа в виде методов для получения ника автора, ссылки на пулреквест, комментарии коммитов и так далее.
Недавно была задача по crm, где приходилось получать всё, что только можно. Вдохновение пришлось черпать в коде модуля, так как документации мало. Публикую, что вызвало трудности и основное время на поиск. Остальное (пользовательские свойства и простые поля, которые входят в основные таблицы сущностей) не описываю.
Получить телефоны, email'ы Контакта
/**
* Получить телефон, факс, email рабочий или личный Контакта
* @return object CDBResult
*/
$rs = CCrmFieldMulti::GetList(
array(),
array('ELEMENT_ID' => $CONTACT_ID)
);
Получить контакты Компании
/**
* Получить контакты Компании
* @return array
*/
$contactIDs = \Bitrix\Crm\Binding\ContactCompanyTable::getCompanyContactIDs($COMPANY_ID);
Получить организации, адреса, банки Компании
/**
* Получение организации Компании
* @return object CDBResult
*/
$requisite = new \Bitrix\Crm\EntityRequisite();
$dbRequisite = $requisite->getList(array('filter' => array('ENTITY_ID' => $COMPANY_ID)));
$arRequisite = $dbRequisite->Fetch();
/**
* Получить банк(и) Компании
* @return object DB\Result
*/
$bank = new \Bitrix\Crm\EntityBankDetail();
$dbRes = $bank->getList(array(
'filter' => array('ENTITY_ID' => $arRequisite['ID'])
));
/**
* Получить адрес(а) Компании
* @return object DB\Result
*/
$address = new \Bitrix\Crm\EntityAddress();
$dbRes = $address->getList(array(
'filter' => array(
'ENTITY_ID' => $arRequisite['ID'],
'ANCHOR_ID' => $COMPANY_ID
)
));
Конечно, более детальное рассмотрения поведения некоторых методов, оставляет больше вопросов, чем ответом, но это работает и данный материал создаёт хорошую отправную точку для решения большинства задач и дальнейшего самостоятельного исследования вопроса.
Я уже вижу, как некоторых личностей трясет в конвульсии от того, что кто-то посмел в очередной раз написать сообщение в ленту, да ещё и решить задачу, которая имеется "из коробки". Но, пожалуйста, дочитайте до конца. Данный материал не о том, кто круче, и не о решении проблем. Я предлагаю уравновешенным людям, разного уровня, досуг в виде решения совместных головоломок и практик программирования. Причем, не обязательно в рамках предложенного решения, а во всём, что угодно. Предлагайте.
Но если это кого-то, по какой-то причине не устраивает или хочется иметь большую гибкость, иметь возможность наследования или изменения поведения, то можно попробовать и данную библиотеку, разработанную уже достаточно давно. Но как это часто бывает, выкидывать жалко, да иногда и пригождается.
Также, данная библиотека может быть хорошей иллюстрацией, для начинающих разработчиков, использования паттерна проектирования Adapter. Паттерн используется для унификации объектов или как в данном случае - протокола OAuth.
Также данная библиотека может быть отличным поводом для контрибуции. Во-первых, пока имеется только три адаптера: Вконтакте, Facebook и Google. Можно их расширить. Во-вторых, в дистрибутив можно включить готовые компоненты авторизации и мульти привязки, к тому же править код библиотеки для этого не потребуется, все данные она уже возвращает и нужный функционал имеет. Такие компоненты я уже делал и они используются на некоторых проектах, но код имеет большую связанность и подойдёт не всем.
В-третьих, можно сделать опциональную надстройку, получения данных (client_id, client_secret) из таблиц модуля социальных сервисов. Надстройка может иметь возможность получения данных и из файла .setting.php, например. По принципу того, как это делают в Laravel. А соответствующая формулировка уже становится интересной задачей для проектирования.
В Битрикс сообществе не очень много инициатив для совместной разработки и OpenSource-проектов, но иногда не хватает общения между разработчиками и обменом опыта. Данный пост и предложенное решение не решает серьезных болей, а в очередной раз нацелен на попытку завязать диалог и поиск дружественных точек соприкосновения.
Евгений, спасибо за более менее конструктивный ответ. Твои сообщения периодически встречаются в ленте, это в основном агрессивные не обоснованные пинки другим участникам сообщества. И согласен с тем, что лучше было бы написать обёртку под битрикс с задуманным мной функционалом по мулти аккаунту и регистрации, чем писать всё полностью. Придётся теперь писать Но давай по меньше эмоций, я рад твоему конструктиву!)
1) Я вижу, что ты адекватный и пытаешься что то сделать. Зачем мне тебя бомбить. Я бомблю только сектантов "битрикс", которые рассуждают об устрицах, не пробовав их 2) С возрастом становишься мягче, безсмысленно метать бисер, понимаешь не сразу 3) Уже весь зад сгорел пытаться доказать людям, что по мимо битрикса есть другой мир и там подход "с умом"
Пили библиотеку) Я не против я только за я даже звезду тебе поставлю.
А вообще да агрессивной составляющей было много - но это от сложностей самореализации в рамках битрикса, но теперь границы пошире, и не так уже бомбит
Я когда решил что битрикс это тупо про бабки - стало даже легче, а для нормальной разработки есть другие сообщества:)
На написание сей статьи меня подтолкнуло неведение некоторых специалистов решения проблемы кеширования статики в браузере клиента. Исходя из чего, делаю вывод, что краткое изложение проблемы не будет лишним и поможет разобраться в вопросе человеку любого уровня, в том числе и менеджерам проектов, так как на практике вижу, что проблема актуальна для всех.
На самом деле всё куда проще и что касается правильно подключенных css и js-файлов через API-битрикса, то тут всё работает с коробки, только это знают не все. Для любого подключаемого файла проблема решается добавлением аргумента ?1487583138267920:
Наверняка, многие из вас видели его при просмотре кода страницы. В этом и есть вся фишка. Имя файла тоже, но путь к файлу браузеры считают новым. Этот код меняется каждый раз после изменения файла и его размера, браузеры видят новый путь и загружают файл повторно.
Тот же самый финт можно выполнить и прямо в коде css файла, но делать это придётся уже вручную или если вы используете какие-нибудь препроцессоры css, то версию файла можно вынести в переменную и не лазить по коду каждый раз:
А всё что касается публичной части сайта, то процесс легко автоматизировать с помощью утилиты, которая использует сама система, при подключении файлов:
Вот только непонятно, зачем это делать? Каждый раз заново грузить? На этапе разработки или создания некоего нового функционала, когда часто редактируются .css и .js - еще понятно. А вот для рабочего сайта кеширование статики на стороне браузера - благо. Разве не так? В случае каких-то разовых изменений, проще вручную добавить аргумент вида ?1487583138267920 Тем более повторная загрузка картинок. Кешируем все и везде, где только можно. Бдительно следим за скоростью генерации страницы. А тут вдруг принудительное обновление кеша без явной нужды.
Погоня за увеличением скорости загрузки страниц продолжается. Представим, что мы всё сжали, минифицировали, объединили в один файл, скрипты "опустили", используем svg-спрайты и всё в этом духе. Что дальше? Одно из трендовых инноваций сегодня (особенно актуально на мобильниках), это размещение стилей верхней части страницы прямо в тег head и асинхронная подгрузка остальных файлов. Данную рекомендацию сплошь и рядом пропагандируют все сервисы тестирования производительности, в том числе и гугловый, так как браузер не начнёт рендерить страницу и не покажет её пользователю, пока не получит все linkи в head. Статья на тему.
В своём примере я не выделяю стили верхней части страницы, а подключаю весь закешированный битриксом файл стилей в теге head. Хочу сразу предупредить, что данный метод стоить тестировать на производительность на конкретном сайте, в некоторых случаях это может увеличить First byte из-за работы с большими строками через регулярные выражения, в некоторых сильно увеличит объём страницы и уменьшит объём кешируемых данных, что приведёт к обратному эффекту.
/* Для замера скорости работы */
$start = microtime(true);
/* Получить пути подключенных файлов стилей */
$css_str = Bitrix\Main\Page\Asset::getInstance()->GetCSS();
preg_match_all('/href="(.*)"\stype/', $css_str, $matches);
/*
* Перебираем результат, так как метод возвращает все подключаемые файлы стилей
* нас интересует только кеш объединённых файлов, содержит в названии 'template_'
*/
foreach($matches[1] as $val)
{
$val = explode('?', $val);
$full_path = $_SERVER['DOCUMENT_ROOT'] . $val[0];
/*
* Производим подмену только для закешированного объединённого файла
* если он существует и не пуст (на пустоту проверка дальше)
*/
if (strpos($full_path, 'template_') !== false && file_exists($full_path))
{
$st yle = trim( file_get_contents($full_path) );
if (!empty($style))
{
$search = '<st yle type="text/css"></style>';
$replace = '<st yle type="text/css">'. $style .'</style>';
// Вставить стили
$content = str_replace($search, $replace, $content);
// Вырезить <li nk>
$content = preg_replace('/<li nk\shref="'. addcslashes($val[0], '/') .'(.*)>/', '', $content);
}
}
}
/* Вставляем время исполнения кода в заранее подготовленное место */
$content = str_replace('#time_replace#', microtime(true) - $start, $content);
Немного истории. Bitrix Framework буфферизирует весь клиентский код. Данный подход делает возможным работу отложенных функций и прочей манипуляции с содержимым сайта «выше», после того как мы находимся уже совершенно в другой части исполнения страницы и не имеем возможности перепроектировать последовательность под конкретный случай.
В своём решении я использую событие OnEndBufferContent (вызывается при выводе буфферизированного контента), у него имеется один аргумент $content – тот самый буфферизированный контент, который мы будем править.
Идеязаключается в том, чтобы найти подключенный закешированный (объединённый и минифицированный) файл стилей, получить его содержимое, вырезать его подключение из кода и вставить содержимое в теге <style> в head. Маркер для вставки в виде пустого блока стилей, на случай если что-то пойдёт не так, страница останется целой и валидной:
<st yle type="text/css"></style>
Метод будет работает стабильно всегда, так как получает имя сгенерированного битриксом файла через специальный api-метод, ищет его в контенте и ещё раз проверяет файл по имени (содержит template_), проверяет его существование на сервере и если он не пустой, вставляет в документ и очищает контент от link’a только вставленного файла.
Результат можно посмотреть здесь, не обещаю, что будет всегда включено Ещё, кстати, убираю css-комментарии и лишние переносы, это просто по фану. Не рекомендую сильно заморачиваться, также не рекомендую заморачиваться по поводу вырезания пробелов или ещё какой-то манипуляции с контентом, так как не стоит забывать, что html-результат сжимается gzip’ом, по хорошему конечно Но когда вы дойдёте до применения вставки стилей в head, то всё остальное по умолчанию у вас будет по феншую.
/*
* Убрать комментарии из стилей и лишние переносы
* можно применить как ко всему контенту, так и только к файлам стилей, но лучше вообще не заморачиваться :)
*/
$arReplace = array(
"/\\/\\*(.*)\\*\\//" => "",
"/\n+/" => "\n",
);
$content = preg_replace(array_flip($arReplace), $arReplace, $content);
Метод протестирован с объединёнными файлами стилей и без, со сжатыми, минифицированными и без. Даже если вдруг произойдёт вставка не того файла, то только его подключение и будет вырезано, но такого замечено не было. Ещё по поводу времени исполнения, решайте сами, что для вас быстро или медленно, смотрите как это влияет на общую скорость отработки страницы в вашем случае. У меня это ~0,0009, но и контента на приведённом в примере сайте очень мало. Также не стоит забывать, что подключенные внешние файлы стилей будут кешироваться браузером и такой прямой подход как здесь увеличит объём страницы и уменьшит кол-во кешируемых данных, так что подходит не везде. Если у вас не много стилей, маленький или среднего размера проект, то скорее всего вы получите прирост. На крупных проектах метод не стоит использовать или стоит дорабатывать.
Ремарка про шрифты,
var resource = document.createElement('link');
resource.setAttribute("rel", "stylesheet");
resource.setAttribute("href","https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700|Open+Sans:400,600&subset=cyrillic,cyrillic-ext");
var head = document.getElementsByTagName('head')[0];
head.appendChild(resource);
Код асинхронно подгружает файлы шрифтов, подключаемых с fonts.googleapis.com. Но это создаёт одну неприятность. После загрузки шрифта, если в этот момент сайт уже отрендерин, страница заметно моргнёт. Проблему наблюдал в chrome, решение искать не стал и от идеи отказался, мигание ушло. Если вас ваше руководство/клиента это устроит, используйте, гугл прибавит вам пару «попугаев» к тесту. Если кому известно в чём причина и как исправить, пишите в комментариях. Наличие или отсутствие data-skip-moving на результат не влияет. При повторном открытие стр. проблемы нет, так как файл шрифтов уже в кеше браузера.
Самый правильный способ такой (ИМХО): 1. Грамотно верстаем. Выделяем стили, отвечающие за скелет страницы. 2. Все эти стили в хеадер пихаем. Можно сделать проверку по кукам и сессии и только при первом посещении в хеадере выдавать эти стили. Причем они же должны дублироваться в основных файлах стилей, которые закэшируются браузером и не будут грузиться второй раз.
Но по оптимизации гораздо больше работ, чем просто стили подключить. 1. Если шрифты неприятно дергают страницу после загрузки - подбираем штатный шрифт с похожими размерами. Тогда при загрузке шрифта разница будет не столь заметна. 2. Грузим шрифты, например, с гугла, если это популярные бесплатные шрифты. Тогда есть вероятность, что у пользователя в браузере уже есть нужный закэшированый скрипт. 3. Не забываем про изображения. Это главный бич на данный момент. Гуглспид стал анализировать всю страницу, а не только верхнюю часть. А для всей сраницы гораздо сложнее заставить грузить оптимизированный контент - поэтому юзаем ленивую загрузку. 4. Ленивая загрузка частично решает проблему картинок для гуглспида, но не решает проблему трафика. a) Битрикс штатно не умеет подсовывать изображения нужного разрешения (да и не должен уметь в общем-то). В итоге грузим банер для разрешения в 2560px шириной и потом все это отображаем на мобильном телефоне. б) Если вы думаете, что скрыв блок баннеров адаптивом (display: none) проблема решается - я вас разочарую. Браузеры грузят это все, чтобы "сайт работал быстро" (раньше мы для этого грузили нужные картинки в блок 1*1пиксел). в) Та же беда с обычными картинками по контенту, только решается чуть сложнее, чем с баннерами. г) И, да. PHP не умеет качественно жать картинки. Гугл все равно ткнет носом, что можно бы ещё несколько кб с каждой картинки срезать, даже если вы уже поставили сжатие "хуже некуда"
Ага, достаточно выделить grid и цвета, фоны элементов.
Sergey Emelyanov написал: 2. Все эти стили в хеадер пихаем. Можно сделать проверку по кукам и сессии и только при первом посещении в хеадере выдавать эти стили. Причем они же должны дублироваться в основных файлах стилей, которые закэшируются браузером и не будут грузиться второй раз.
Куку будет сложно с композитом подружить, особенно, если композитный кеш отдается ngix-ом.
Точно, про композит забыл. Теоретически, если грамотно выделить нужные стили - это 2-3 кб дополнительно к странице (если жмется сервером страница и того меньше). Думаю это не столь критично.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».