Небольшое, но удобное для использования 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
GitHub: (есть более подробное описание работы) Пример использования: (хорошие примеры разных типов компонентов) Страница примера:
Представим, что нам надо отправлять сообщения в Битрикс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
)
));
Конечно, более детальное рассмотрения поведения некоторых методов, оставляет больше вопросов, чем ответом, но это работает и данный материал создаёт хорошую отправную точку для решения большинства задач и дальнейшего самостоятельного исследования вопроса.
Я уже вижу, как некоторых личностей трясет в конвульсии от того, что кто-то посмел в очередной раз написать сообщение в ленту, да ещё и решить задачу, которая имеется "из коробки". Но, пожалуйста, дочитайте до конца. Данный материал не о том, кто круче, и не о решении проблем. Я предлагаю уравновешенным людям, разного уровня, досуг в виде решения совместных головоломок и практик программирования. Причем, не обязательно в рамках предложенного решения, а во всём, что угодно. Предлагайте.
Регистрация пользователей через соц. сети решается и .
Но если это кого-то, по какой-то причине не устраивает или хочется иметь большую гибкость, иметь возможность наследования или изменения поведения, то можно попробовать и данную библиотеку, разработанную уже достаточно давно. Но как это часто бывает, выкидывать жалко, да иногда и пригождается.
Привёл код в надлежащий для публикации вид и делюсь с общественностью:
Также, данная библиотека может быть хорошей иллюстрацией, для начинающих разработчиков, использования паттерна проектирования . Паттерн используется для унификации объектов или как в данном случае - протокола OAuth.
Также данная библиотека может быть отличным поводом для контрибуции. Во-первых, пока имеется только три адаптера: Вконтакте, Facebook и Google. Можно их расширить. Во-вторых, в дистрибутив можно включить готовые компоненты авторизации и мульти привязки, к тому же править код библиотеки для этого не потребуется, все данные она уже возвращает и нужный функционал имеет. Такие компоненты я уже делал и они используются на некоторых проектах, но код имеет большую связанность и подойдёт не всем.
В-третьих, можно сделать опциональную надстройку, получения данных (client_id, client_secret) из таблиц модуля социальных сервисов. Надстройка может иметь возможность получения данных и из файла .setting.php, например. По принципу того, как это делают в Laravel. А соответствующая формулировка уже становится интересной задачей для проектирования.
В Битрикс сообществе не очень много инициатив для совместной разработки и OpenSource-проектов, но иногда не хватает общения между разработчиками и обменом опыта. Данный пост и предложенное решение не решает серьезных болей, а в очередной раз нацелен на попытку завязать диалог и поиск дружественных точек соприкосновения.
Однажды мне доводилось немного котрибьютить интересное решение , там и до сих пор имеются открытые ишью и пространства для размышления.
Если и у вас есть такие проекты или идеи для совместного решения, пожалуйста в комментарии!
На написание сей статьи меня подтолкнуло неведение некоторых специалистов решения проблемы кеширования статики в браузере клиента. Исходя из чего, делаю вывод, что краткое изложение проблемы не будет лишним и поможет разобраться в вопросе человеку любого уровня, в том числе и менеджерам проектов, так как на практике вижу, что проблема актуальна для всех.
На самом деле всё куда проще и что касается правильно подключенных css и js-файлов через API-битрикса, то тут всё работает с коробки, только это знают не все. Для любого подключаемого файла проблема решается добавлением аргумента ?1487583138267920:
Наверняка, многие из вас видели его при просмотре кода страницы. В этом и есть вся фишка. Имя файла тоже, но путь к файлу браузеры считают новым. Этот код меняется каждый раз после изменения файла и его размера, браузеры видят новый путь и загружают файл повторно.
Тот же самый финт можно выполнить и прямо в коде css файла, но делать это придётся уже вручную или если вы используете какие-нибудь препроцессоры css, то версию файла можно вынести в переменную и не лазить по коду каждый раз:
А всё что касается публичной части сайта, то процесс легко автоматизировать с помощью утилиты, которая использует сама система, при подключении файлов:
Погоня за увеличением скорости загрузки страниц продолжается. Представим, что мы всё сжали, минифицировали, объединили в один файл, скрипты "опустили", используем 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С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».