Magento 2: Advanced JavaScript Bundling

Большой размер JavaScript файлов в Magento2 - большая проблема, в этой статье мы попробуем Magento Advanced JavaScript Bundling. Рассмотрим инструменты, настройку и работоспособность.

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

В дефолтной версии бандлинга на каждую страницу подгружается абсолютно весь "набор" сбандленных JavaScript файлов.

Magento 2: Настройки frontend оптимизации

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

Advanced JavaScript Bundling помогает решить эту задачу, а именно, сформировать бандлы по типам страниц. Например, общий бандл для JavaScript файлов, которые нужны на каждой странице, и отдельные бандлы для чекаута, категории, продуктовой страницы, CMS-страниц и пр.

Звучит красиво, но на деле не все так хорошо, как может показаться.

В официальной документации есть статья, как настроить advanced JavaScript bundling.

В ней предлагается несколько вариантов:

  • Ручная настройка - основана на RequireJS optimizer
  • Модуль Magento_Baler

Ручной режим

Первый вариант - очень сложный и трудоемкий, подразумевает ручное составление конфигурации под каждый бандл. Поддержка проекта так же очень сильно пострадает.

Для реализации требуется наличие следующих инструментов:

Пример билд-файла можно посмотреть тут

После того, как мы проделали всю кропотливую работу по составлению билд-файла, необходимо выполнить генерацию статики:

php -f bin/magento setup:static-content:deploy -f -a frontend

Далее перенести содержимое статики во временных каталог:

mv pub/static/frontend/Magento/{theme}/{locale} pub/static/frontend/Magento/{theme}/{locale}_tmp

Затем запустить r.js optimizer для файла билд-файла:

r.js -o build.js baseUrl=pub/static/frontend/Magento/{theme}/{locale}_tmp dir=pub/static/frontend/Magento/{theme}/{locale}

Эта команда генерирует бандлы в подкаталог bundles корневого каталога Magento:

pub/static/frontend/Magento/{theme}/{locale}/bundles

total 1900
drwxr-xr-x  2 root root    4096 Mar 28 11:24 ./
drwxr-xr-x 70 root root    4096 Mar 28 11:24 ../
-rw-r--r--  1 root root  116417 Mar 28 11:24 cart.js
-rw-r--r--  1 root root  187090 Mar 28 11:24 catalog.js
-rw-r--r--  1 root root  307619 Mar 28 11:24 checkout.js
-rw-r--r--  1 root root 1240608 Mar 28 11:24 default.js
-rw-r--r--  1 root root   74233 Mar 28 11:24 shipping.js

Чтобы RequireJS использовал эти бандлы, необходимо добавить onModuleBundleComplete callback в файле build.js:

[
    {
       //...
       exclude: [
           'requirejs/require',
           'bundles/default',
           'bundles/checkout',
           'bundles/cart',
           'bundles/shipping',
           'mage/bootstrap'
       ],
   },
],
bundlesConfigOutFile: `${config.dir}/requirejs-config.js`,
onModuleBundleComplete: function(data) {
    if (this.bundleConfigAppended) {
        return;
    }
    this.bundleConfigAppended = true;

    // bundlesConfigOutFile requires a simple require.config call in order to modify the configuration
    const bundleConfigPlaceholder = `
(function (require) {
require.config({});
})(require);
    `;

    fs.appendFileSync(this.bundlesConfigOutFile, bundleConfigPlaceholder);
}

Далее, запустить команду

r.js -o app/design/frontend/Magento/luma/build.js baseUrl=pub/static/frontend/Magento/{theme}/{locale}_tmp dir=pub/static/frontend/Magento/{theme}/{locale}

Если мы откроем requirejs-config.js в pub/static/frontend/Magento/{theme}/{locale}, то увидим следующее:

require.config({
    bundles: {
        "bundles/default": ["mage/template", "mage/apply/scripts", "mage/apply/main", "mage/mage", "mage/translate", "mage/loader"],
        "bundles/cart": ["Magento_Ui/js/lib/validation/utils", "Magento_Ui/js/lib/validation/rules", "Magento_Ui/js/lib/validation/validation"]
    }
}

Для "сжатия" бандлов мы можем можем добавить следующую конфигурацию в билд-файле:

({
    optimize: 'uglify2',
    inlineText: true
})

Magento_Baler

Модуль Magento_Baler - использует схожие принципы первого метода, но добавляется автоматизация. К сожалению, в данный момент этот модуль находится в стадии раннего alpha-тестирования, не стабилен и содержит в ряд ошибок.

Так же существует ряд сторонних решений:

  1. WeareJH/config-gen
  2. magento/m2-devtools
  3. magesuite/magepack

На данный момент времени нет готового работающего инструмента для реализации этой задачи. Все примеры реализованы на базовой теме Luma, в случае полноценного интернет-магазина на Magento, который, как правило, включает в себя ряд сторонних модулей - нет никаких гарантий оптимальной работы этих модулей при advanced JavaScript bundling.