Повышение производительности в XenForo 2.3

  • Меценат
В сегодняшней статье "Видели ли вы...?", посвященной XenForo 2.3, мы рассмотрим, как мы сосредоточились на повышении производительности, обеспечивая быстрое и бесперебойное функционирование вашего сообщества. Мы подробно рассмотрим, какие улучшения были сделаны и как они соотносятся с различными показателями производительности.

Но прежде чем перейти к рассмотрению отдельных изменений, давайте взглянем на базовый уровень - это наш текущий показатель производительности, рассчитанный компанией Lighthouse для списка форумов XenForo Community:

googlechrome.github.io_lighthouse_viewer_.png
Вот оценки производительности некоторых других программ для форумов:

1.png2.png3.png
Важно отметить, что хотя этот результат является эталоном производительности, он не является единственным показателем успеха. Действительно, результаты могут незначительно колебаться при многократном тестировании. Сайт может пользоваться популярностью и при более низких показателях, но более высокий рейтинг, несомненно, улучшает как рейтинг в поисковых системах, так и общее впечатление пользователей.

Следите за новостями! В ближайшее время мы сообщим обновленный рейтинг XenForo 2.3. Но прежде давайте познакомимся с изменениями, которые привели нас сюда.

Если Вы хотите перейти к какому-либо разделу, воспользуйтесь ссылками ниже.

Улучшения в работе Font Awesome
Производительность JavaScript
Прощай, jQuery
Улучшение производительности CSS с помощью HTTP/2+
Заключение

Если же вы хотите пропустить много чтения, ознакомьтесь с приведенным ниже TL;DR:

Для просмотра этого контента нам потребуется ваше согласие на установку файлов cookie третьих лиц.
Более подробную информацию можно найти на нашей странице cookie.

Если вы опасаетесь, что в XenForo 2.3 мы покажем вам только улучшение производительности, то это не так.

На следующей неделе мы покажем совершенно новую функцию!
 

Улучшения в Font Awesome​


Практически на каждой странице мы используем до пяти различных вариантов библиотеки иконок Font Awesome 5 Pro. Это до 8 тыс. иконок в разных вариантах, но на каждой конкретной странице мы используем... гораздо меньше. Размер файла каждого из этих шрифтов составляет до 200 КБ с дополнительным CSS размером 40 КБ.

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

Еще в 2019 году мы создали прототип, очень похожий на отличное дополнение Font Awesome Manager, выпущенное , но в итоге решили, что это не совсем тот подход, который мы хотим использовать.

В XenForo 2.3 мы разработали совершенно новый способ подмножества иконок Font Awesome, благодаря которому пользователям будут предоставляться только те иконки, которые действительно используются в вашей установке XenForo, и, что еще лучше, это происходит полностью автоматически!

Анализатор использования иконок​

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

Способ использования иконок существенно не изменился по сравнению с тем, что было в XF 2.2. Например, если вы знакомы с использованием, например, <xf:fa icon="fa-comments" /> в шаблонах или .m-faContent(@fa-var-comments) в шаблонах Less, то все готово.

Однако некоторые подходы больше не будут работать. Например, использование <i class="fas fa-comments"></i> больше не будет работать. Такие варианты использования не будут анализироваться и не приведут к отображению значка. В связи с этим появился совершенно новый синтаксис для использования во фразах.

Примеры приведены в таблице ниже:

Тип​
Код​
Шаблоны / модификации шаблонов
HTML:
<xf:fa icon="fas fa-comments" />
Less шаблоны
Less:
.m-faContent(@fa-var-solid-comments);
JavaScript
JavaScript:
XF.Icon.getIcon('solid', 'fa-comments')
Фразы
Код:
{icon:fas::comments}

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

Рендеринг иконок​

Итак, что же мы делаем с проанализированными иконками? Вместо того чтобы работать с несколько неудобным форматом файла шрифта, мы используем полученную информацию для создания спрайтового листа SVG. На самом деле, не просто одного, а по одному для каждого из стилей Font Awesome 5 Pro - light, solid, regular и duotone, и каждый из них содержит только те значки, которые мы анализируем в этих стилях.

Например, вот полный объем спрайт-листа, который мы генерируем для стиля solid по умолчанию:

XML:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Font Awesome Pro by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license (Commercial License)
-->
<svg xmlns="http://www.w3.org/2000/svg">

    <symbol id="check-circle" viewBox="0 0 512 512">
        <path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/>
    </symbol>
    <symbol id="exclamation-circle" viewBox="0 0 512 512">
        <path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>
    </symbol>
</svg>

Он загружается только на тех страницах, которые действительно используют эти иконки, но что еще лучше, так это то, что если раньше мы загружали полный файл шрифта размером 137 КБ, то этот спрайт-лист весит всего 726 байт.

В целом, общий размер файлов, которые мы загружали для иконок по умолчанию на главной странице форума, составлял около 400 КБ, теперь он будет менее 40 КБ.
 

Производительность JavaScript​

Теперь мы должны переключить наше внимание на JavaScript и посмотреть на потенциальную экономию производительности, которую мы там заложили.

Нативная отсрочка для JavaScript​

За прошедшие годы стандарты JavaScript претерпели значительные изменения. Еще не так давно наилучшей практикой было перемещение тегов <script> в нижнюю часть HTML, чтобы отложить выполнение необходимого кода на стороне клиента на как можно более поздний срок, с тем чтобы как можно больше содержимого страницы было разобрано в первую очередь, прежде чем все более сложный код JavaScript загрузится и заблокирует оставшуюся часть разбора страницы.

К счастью, JavaScript и большинство современных браузеров поддерживают новую директиву defer для тегов <script>, что позволяет нам перемещать их обратно в верхнюю часть DOM.

Это позволяет браузеру начать загрузку скриптов несколько раньше, отложив их выполнение до загрузки остальной части DOM.

Ленивая загрузка обработчиков JS​

В предыдущих версиях XenForo огромная часть нашего JavaScript-кода считалась "ядром" JavaScript, скомпилированным в один файл, который загружался на каждой странице. В XenForo 2.3 мы создали систему "ленивой" загрузки часто используемых обработчиков, когда они необходимы. Они по-прежнему сгруппированы в обработчики form (форм), action (действий), structure (структуры) и tooltip (всплывающих подсказок), но вместо того, чтобы загружать все эти обработчики на каждой странице, они теперь загружаются и регистрируются только в том случае, если это необходимо на текущей странице.

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

Прощание с jQuery​

После того как jQuery стал частью нашего продукта с самого начала, настало время попрощаться с ним.

jQuery - это JavaScript-библиотека, которая инкапсулирует большое количество собственных функций JavaScript в альтернативный набор функций, обильно посыпая их синтаксическим сахаром.

За время существования XenForo стандарты JavaScript и браузеров претерпели значительные изменения. Когда-то использование чего-либо другого было просто немыслимо. В недалеком прошлом jQuery был практически необходим даже для того, чтобы найти элемент с определенным именем класса, или для поддержки, казалось бы, бесконечных причуд в устаревших версиях Internet Explorer и других.

Да и сама по себе эта библиотека занимает более 30 КБ при каждой загрузке страницы, а сколько из этой библиотеки мы на самом деле использовали?

Ну, как разработчик ( ), который лично просмотрел и переписал почти 40 000 строк кода, скажу, что это гораздо меньше, чем можно подумать. А из тех языковых возможностей jQuery, которые мы использовали, многие вещи являются простой прямой заменой на родную функцию JavaScript, которая давным-давно либо вообще не существовала, либо была слишком новой, чтобы получить достаточную поддержку браузера.

Мы понимаем, что для разработчиков, имеющих существующий код на основе jQuery, возникнут некоторые болевые точки, но, по правде говоря, если вы не поддерживаете и близко 40 000 строк кода, которые поддерживаем мы (разработчики XenForo), переход должен быть относительно плавным. Но если вы совсем застряли, то при желании всегда можно заново добавить jQuery, но мы бы рекомендовали избегать этого, если есть такая возможность. А удаление jQuery как зависимости можно начать уже сейчас, если вы планируете вносить изменения в существующий код до выхода XenForo 2.3. Мы настоятельно рекомендуем воздержаться от написания нового кода, напрямую использующего функциональность jQuery.


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

Примечание: Следующий раздел посвящен специфике разработки, поэтому, если это вас не интересует, переходите к следующему разделу.

Переменные с привязкой к блоку​

Хотя это и не относится к jQuery, стоит отметить, что мы больше не используем для определения переменных, а предпочитаем использовать и . Это делает определение переменных более понятным, а код менее подверженным ошибкам и более предсказуемым.

Выбор элемента(ов)​

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

jQuery / XF 2.2​

JavaScript:
var $element = $('.someClassName')
if ($element.length)
{
   // you have an object containing one or more elements; you can call various methods which will interact with this element or elements
}

JavaScript / XF 2.3​

JavaScript:
const element = document.querySelector('.someClassName')
if (element)
{
    // you have an instance of HTMLElement, if more elements exist with the same selector, you have the first element
}

// ... or

const elements = document.querySelectorAll('someClassName')
if (elements.length)
{
    // you have a NodeList object containing one or more HTMLElement objects
}

Стрелочные функции​

Опять же, хотя это и не связано с jQuery, в настоящее время используются как можно чаще. Помимо того, что они синтаксически более удобны, чем традиционные анонимные функции, они не создают новых привязок для ключевых слов, таких как this.

jQuery / XF 2.2​

JavaScript:
var self = this
var callback = function (foo)
{
    self.doSomething(foo)
}

JavaScript / XF 2.3​

JavaScript:
const callback = (foo) =>
{
    this.doSomething(foo)
}

// ...or

const callback = (foo) => this.doSomething(foo)

Обработка событий​

От некоторых функциональных возможностей, предоставляемых jQuery, было трудно отказаться, и большинство этих действительно полезных методов были переписаны и перенесены на ванильный JavaScript в качестве дополнительных методов нашего объекта XF. Не последнюю роль в этом играет управление событиями в jQuery, которое поддерживает события с именами и обеспечивает более интуитивный способ удаления слушателей событий из элемента, не требующий ссылки на исходный обратный вызов события.

jQuery / XF 2.2​

JavaScript:
var $element = $('.someClassName')
$element.on('namespace.click', function (e)
{
   e.preventDefault()
    $element.off('namespace.click')
});

JavaScript / XF 2.3​

JavaScript:
const element = document.querySelector('.someClassName')
if (element)
{
    XF.on(element, 'namespace.click', e =>
    {
        e.preventDefault()
        XF.off(element, 'namespace.click')
    })
}

AJAX​

По сравнению с XenForo 2.2 ситуация в основном не изменилась, поскольку мы по-прежнему используем обертку XF.ajax() в качестве вспомогательного метода, но за кулисами вместо использования метода $.ajax() из jQuery (который является оберткой вокруг XMLHttpRequest) мы перешли на использование более современного .

Главное, на что следует обратить внимание, - это то, что методы , доступные в результате вызова XF.ajax(), называются несколько иначе, чем в jQuery.

jQuery / XF 2.2​

JavaScript:
var t = this
XF.ajax('some-url', data, callback)
    .always(function ()
    {
        t.loading = false
    })

JavaScript / XF 2.3​

JavaScript:
XF.ajax('some-url', data, callback)
    .finally(() =>
    {
        this.loading = false
    })

Хранение произвольных данных для элемента​

Некоторые возможности jQuery, несмотря на свою мощь, иногда могут показаться непоследовательными или неоднозначными. Одной из таких возможностей является метод data, доступный для объектов jQuery. В зависимости от его использования он может вести себя по-разному. Рассмотрим следующий пример:

jQuery / XF 2.2​

JavaScript:
var $element = $('.someClassName').first() // <span class="someClassName" data-foo="1"></span>

var foo = $element.data('foo') // reads the data-foo attribute from the element in the DOM

var bar = $element.data('bar') // attempts to read the data-bar attribute from the element which doesn't exist, but the internal data store may have a value set

$element.data('bar', [1, 2, 3]) // sets the bar key in the internal data store to an array

$element.data('foo', '100') // the foo entry in the internal data store for this element now returns 100, ignoring the data-foo attribute which remains unchanged in the actual DOM

В XenForo по-прежнему существует необходимость хранить произвольные данные, особенно те, которые не всегда являются строкой. Однако наши современные подходы более предсказуемы и последовательны:

JavaScript / XF 2.3​

JavaScript:
const element = document.querySelector('.someClassName') // <span class="someClassName" data-foo="1"></span>

const foo = element.dataset.foo // reads the data-foo attribute from the DOM

element.dataset.foo = '100' // sets the data-foo attribute in the DOM

XF.DataStore.set(element, 'bar', [1, 2, 3]) // a new XF.DataStore class is introduced for reading / storing arbitrary, non-string data

const bar = XF.DataStore.get(element, 'bar') // returns an array: [1, 2, 3]

Цели обработчиков​

У нас есть специальная переменная, которую мы передаем во все обработчики элементов/событий, в настоящее время это this.$target. Обратите внимание, что в XF 2.3 она становится this.target, поскольку обычно префикс $ в именах переменных используется для обозначения объекта jQuery. В XF 2.3 this.target представляет собой объект HTMLElement.

Для поиска дочерних элементов целевого объекта это немного больше соответствует стандартному JavaScript, чем jQuery:

jQuery / XF 2.2​

JavaScript:
var $child = this.$target.find('.someChild').first() // returns the first child element which matches the someChild class

JavaScript / XF 2.3​

JavaScript:
const child = this.target.querySelector('.someChild') // returns the first child element which matches the someChild class; this will be a HTMLElement; note it uses the same querySelector method rather than a separately named method

Поддержка миграции
Хотя, по понятным причинам, некоторые пользовательские методы в XF 2.3 будут недоступны для вас до релиза, мы рекомендуем вам уже сейчас начать переносить как можно больше кода, чтобы использовать ванильный JavaScript там, где это возможно.

Если вы считаете, что вам нужна поддержка в переводе кода на ванильный JavaScript, мы имеем около 40 000 строк опыта, и мы (разработчики XenForo) постараемся ответить на запросы в , где это возможно.
 

Повышение производительности CSS с помощью HTTP/2+​

Одним из ключевых преимуществ веб-серверов, работающих по протоколу HTTP/2 и выше, является поддержка мультиплексирования. Мультиплексирование позволяет одновременно обрабатывать несколько запросов к ресурсам (например, JavaScript и CSS), что снижает накладные расходы и увеличивает скорость загрузки страниц.

В XenForo 2.3 мы оптимизировали эту функциональность, изменив способ выполнения CSS-запросов.
  • Основной CSS, единый для всех страниц, по-прежнему упаковывается в один запрос.
  • Теперь CSS, характерный для отдельных шаблонов или страниц, будет запрашиваться отдельно, а не в комплексе.
Для более наглядного представления этих изменений см. ниже.

До.​

HTML:
<link rel="stylesheet" href="css.php?css=public:normalize.css,public:fa.css,public:variations.less,public:core.less,public:app.less" />
<link rel="stylesheet" href="css.php?css=public:node_list.less,public:notices.less,public:share_controls.less,public:extra.less" />

После.​

HTML:
<link rel="stylesheet" href="css.php?css=public:normalize.css,public:fa.css,public:variations.less,public:core.less,public:app.less" />
<link rel="stylesheet" href="css.php?css=public:node_list.less" />
<link rel="stylesheet" href="css.php?css=public:notices.less" />
<link rel="stylesheet" href="css.php?css=public:share_controls.less" />
<link rel="stylesheet" href="css.php?css=public:extra.less" />

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

Барабанная дробь, пожалуйста...​

Ранее мы уже рассказывали о нескольких оптимизациях, внесенных в XenForo 2.3, каждая из которых была направлена на повышение рейтинга производительности Lighthouse:

Переход на спрайтовые листы SVG для Font Awesome, что уменьшает необходимость загрузки полных веб-шрифтов.
  • Внедрение встроенного defer для тегов <script>.
  • Реализация ленивой загрузки для JS-обработчиков.
  • Уменьшение размера страницы за счет удаления jQuery в качестве зависимости.
  • Использование возможностей мультиплексирования HTTP/2 и развязывание CSS.
Благодаря этим усовершенствованиям XenForo 2.3 значительно улучшился по сравнению с показателем Lighthouse, составлявшим 84 балла в XenForo 2.2. Каждое усовершенствование играет важную роль: от передовых методов загрузки JavaScript до оптимизации размера ответа и использования возможностей современных веб-серверов.

Но доказательство, как говорится, в пудинге:

googlechrome.github.io_lighthouse_viewer_ (1).png
Эта высокая производительность постоянно наблюдается во всем программном обеспечении:

googlechrome.github.io_lighthouse_viewer_ (2).pnggooglechrome.github.io_lighthouse_viewer_ (3).png

Несмотря на то, что мы уже приблизились к 100 баллам, ожидаем еще больших улучшений с появлением нового стиля в XenForo 3.0.
 
Ну вот, опять куча модов отвалится, уже на этапе 2.3
 
Ждём с нетерпением. Конечно плохо, что большинство стилей и плагинов перестанет стабильно функционировать на этой версии...
 
мы уже приблизились к 100 баллам
Интересно только одно- на каком железе у них стоит форум.... А то потом окажется что они этих результатов добились на
4x Xeon-2678v3
48 ядер
512 GB RAM....
 
Современный облачный хостинг провайдер | Aéza
Назад
Сверху Снизу