MG DEV

Otimização avançada para Magento 2 – Melhoria de performance no backend e frontend

O Magento 2 como já sabemos, tem uma lista bem grande de dependências e muitas vezes elas não fazem sentido para sua loja e acaba consumindo mais memoria, cpu e em alguns casos, impactando a velocidade da loja no navegador (JS, CSS). Essa configuração irá impactar e muito o SEO  da loja, por melhorar a velocidade do site.

Esse não é um post “clichê”, daqueles que mostra que você precisar fazer, a intenção aqui é mostrar como fazer, ou como otimizar de verdade o Magento 2, então em caso de dúvidas ou problemas, deixe nos comentários.

  1. Otimização no /composer.json.
  2. Otimização de cache L2 e outros itens em /app/etc/env.php.
  3. Desativação de módulos opcionais.
  4. Otimização do frontend, no caso, o JavaScript com Megapack, o Baler ficou parado no tempo.

Otimizando o composer.json do Magento 2.

Aqui podemos remover alguns módulos. Alguns módulos não são necessários para sua loja, mas são necessários para o núcleo do Magento, em outras palavras, se você desabilitar eles aqui, irá gerar vários erros ao compilar “php bin/magento setup:di:compile”, então você deve ficar atento a isso. Faça testes.

Vamos lá, você pode adicionar o blogo  replace: {} logo após o ‘require’: {}, veja o exemplo de como fica o arquivo completo no Github.

Observe que este é um exemplo de uma loja Magento 2.4 em produção, talvez você precise de alguns desses módulos, então basta remover da lista, exemplo:

    "require": {        
 "magento/product-community-edition": "2.4.1",
        "magento/composer-root-update-plugin": "~1.0"
    },
    "replace": {
 "magento/module-wishlist-analytics": "*",
 "magento/module-offline-shipping": "*",
 "magento/module-login-as-customer-sales": "*",
 "magento/module-login-as-customer-quote": "*",
 "magento/module-login-as-customer-page-cache": "*",
 "magento/module-login-as-customer-log": "*",
 "magento/module-login-as-customer-frontend-ui": "*",
 "magento/module-login-as-customer-assistance": "*",
 "magento/module-login-as-customer-api": "*",
 "magento/module-login-as-customer-admin-ui": "*",
 "magento/module-login-as-customer": "*",
 "magento/google-shopping-ads": "*",
 "magento/module-bundle-graph-ql": "*",
 "magento/module-bundle-import-export": "*",
 "magento/module-customer-downloadable-graph-ql": "*",
 "magento/module-downloadable-graph-ql": "*",
 "magento/module-downloadable-import-export": "*",
 "magento/module-google-adwords": "*",
 "magento/module-google-analytics": "*",
 "magento/module-google-optimizer": "*",
 "magento/module-grouped-import-export": "*",
 "magento/module-grouped-product-graph-ql": "*",
 "magento/module-inventory-in-store-pickup-shipping-admin-ui": "*",
 "magento/module-inventory-in-store-pickup-webapi-extension": "*",
 "magento/module-inventory-in-store-pickup-shipping-api": "*",
 "magento/module-inventory-in-store-pickup-shipping": "*",
 "magento/module-inventory-in-store-pickup-sales-api": "*",
 "magento/module-inventory-in-store-pickup-sales-admin-ui": "*",
 "magento/module-inventory-in-store-pickup-sales": "*",
 "magento/module-inventory-in-store-pickup-quote-graph-ql": "*",
 "magento/module-inventory-in-store-pickup-quote": "*",
 "magento/module-inventory-in-store-pickup-multishipping": "*",
 "magento/module-inventory-in-store-pickup-graph-ql": "*",
 "magento/module-inventory-in-store-pickup-frontend": "*",
 "magento/module-inventory-in-store-pickup-api": "*",
 "magento/module-inventory-in-store-pickup-admin-ui": "*",
 "magento/module-inventory-in-store-pickup": "*",
 "magento/module-csp": "*",
 "magento/module-tinymce-3": "*",
 "magento/module-weee": "*",
 "magento/module-weee-graph-ql": "*",
 "magento/module-tax-import-export": "*",
        "magento/module-two-factor-auth": "*",
        "magento/module-cardinal-commerce": "*",
        "magento/module-re-captcha-send-friend": "*",
        "magento/module-re-captcha-paypal": "*",
        "magento/module-re-captcha-version-2-invisible": "*",
        "magento/module-re-captcha-version-2-checkbox": "*",
        "magento/module-swagger": "*",
        "magento/module-swagger-webapi-async": "*",
        "magento/module-swagger-webapi": "*",
        "magento/magento2-functional-testing-framework": "*",
        "magento/language-nl_nl": "*",
        "magento/module-adobe-ims-api": "*",
        "magento/module-adobe-ims": "*",
        "magento/module-adobe-stock-client-api": "*",
        "magento/module-adobe-stock-client": "*",
        "magento/module-adobe-stock-image-api": "*",
        "magento/module-adobe-stock-asset-api": "*",
        "magento/module-adobe-stock-admin-ui": "*",
        "magento/module-adobe-stock-image-admin-ui": "*",
        "magento/module-adobe-stock-image": "*",
        "magento/module-adobe-stock-asset": "*",
        "magento/adobe-stock-integration": "*",
        "astock/stock-api-libphp": "*",
        "paypal/module-braintree": "*",
        "paypal/module-braintree-graph-ql": "*",
        "magento/module-vault": "*",
        "magento/module-instant-purchase": "*",
        "magento/module-paypal": "*",
        "braintree/braintree_php": "*",
        "paypal/module-braintree-core": "*",
        "temando/module-shipping-remover": "*",
        "temando/module-shipping": "*",
        "amzn/amazon-pay-sdk-php": "*",
        "amzn/amazon-pay-and-login-with-amazon-core-module": "*",
        "amzn/login-with-amazon-module": "*",
        "amzn/amazon-pay-module": "*",
        "amzn/amazon-pay-and-login-magento-2-module": "*",
        "magento/module-send-friend": "*",
        "dotmailer/dotmailer-magento2-extension": "*",
        "dotmailer/dotmailer-magento2-extension-chat": "*",
        "dotmailer/dotmailer-magento2-extension-package": "*",
        "yotpo/magento2-module-yotpo-reviews": "*",
        "yotpo/magento2-module-yotpo-reviews-bundle": "*",
        "vertex/sdk": "*",
        "vertex/module-tax": "*",
        "vertex/module-address-validation": "*",
        "vertex/product-magento-module": "*",
        "klarna/module-core": "*",
        "klarna/module-onsitemessaging": "*",
        "klarna/module-ordermanagement": "*",
        "klarna/module-kp": "*",
        "klarna/m2-payments": "*",
        "magento/language-zh_hans_cn": "*",
        "magento/language-fr_fr": "*",
        "magento/language-es_es": "*",
        "magento/language-de_de": "*",
        "magento/module-vault-graph-ql": "*",
        "magento/module-usps": "*",
        "magento/module-ups": "*",
        "magento/module-send-friend-graph-ql": "*",
        "magento/module-sample-data": "*",
        "magento/module-paypal-graph-ql": "*",
        "magento/module-paypal-captcha": "*",
        "magento/module-new-relic-reporting": "*",
        "magento/module-fedex": "*",
        "magento/module-elasticsearch-6": "*",
        "magento/module-dhl": "*"
    }

Aplique a atualização no composer, faça o upgrade no Magento, deploy, compiler e por fim, teste se está tudo funcinando:

composer update
rm -fr var/log/* var/report/* var/view_preprocessed/* pub/static/frontend/*
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f
php bin/magento setup:di:compile
php bin/magento cache:clean

Teste!

Logo no início, com essa otimização você  estará desabilitando mais de 100 módulos. Se você teve algum problema, deixa nos comentários.

2 – Cache em dois níveis no Magento 2 com Redis e Preload ativado.

Consulte a documentação oficial sobre o cache “L2”: https://devdocs.magento.com/guides/v2.4/config-guide/cache/two-level-cache.html

Na documentação oficial você pode entender melhor como funciona mas irei deixar algumas observações importantes.

1 – Verifique a configuração do seu redis-server se está para conectar via http ou unix.
2 – Se você não quer usar cache em dois níveis,  mas quer usar o recurso preload do redis, você não precisa do :hash, por exemplo, pode usar apenas 061_EAV_ENTITY_TYPES.
3 – A partir do Magento 2.4, introduzimos uma stale_cacheopção que pode melhorar o desempenho em alguns casos específicos. O cache obsoleto funciona apenas com um cache L2. Com um cache obsoleto, você pode enviar um cache desatualizado, enquanto um novo está sendo gerado em um processo paralelo. Para habilitá-lo, basta adicionar 'use_stale_cache' => truea configuração superior do cache L2.
4 – Observe que eu deixei o cache local_backend na memoria compartilhada, caso não queira usar a memória, você pode especificar um outro caminho, ex var/cache.
5 – Talvez você queira alterar as chaves que estão sendo pré-carregadas ‘preload_keys’. Como informado na documentação oficial. você deve monitorar as chaves que fazem mais sentido para você, por exemplo, aquelas que estão sendo chamadas várias vezes em todas as páginas utilizando o comando  redis-cli monitor, consulte a documentação: https://devdocs.magento.com/guides/v2.4/config-guide/redis/redis-pg-cache.html#redis-preload-feature .
5 – Tive alguns erros nessa configuração ao informar ‘compression_lib’ algum método, então eu não uso e não dei muita atenção aos erros pois a compressão desativada, temos melhor desempenho.
6 – Procure saber sobre cada item de configuração que está sendo adicionado em sua loja, evite simplesmente fazer um “Ctr + c e Ctr + v”.

Não fique com dúvida, consulte a documentação ou deixe aqui mesmo nos comentários. Irei aprofundar melhor no assunto trazendo alguns benchmarks com essas configurações.

Em /app/etc/env.php

'cache' => [
        'frontend' => [
            'default' => [
                'id_prefix' => '061_',
                'backend' => '\\Magento\\Framework\\Cache\\Backend\\RemoteSynchronizedCache',
                'backend_options' => [
                    'use_stale_cache' => true,
                    'remote_backend' => '\\Magento\\Framework\\Cache\\Backend\\Redis',
                    'remote_backend_options' => [
                        'persistent' => 0,
                        'server' => '/var/run/redis/redis-server.sock',
                        'database' => '0',
                        'port' => '',
                        'password' => '',
                        'compress_data' => '0',
                        'compression_lib' => '',
                        'compress_tags' => '0',
                        'connect_retries' => 3,
                        'timeout' => '5',
                        'preload_keys' => [
                            '061_EAV_ENTITY_TYPES:hash',
                            '061_GLOBAL_PLUGIN_LIST:hash',
                            '061_DB_IS_UP_TO_DATE:hash',
                            '061_SYSTEM_DEFAULT:hash',
                            '061_SYSTEM_STORES_DEFAULT:hash',
                            '061_SYSTEM_WEBSITES_BASE:hash',
                            '061_FRONTEND__EVENT_CONFIG_CACHE:hash',
                            '061_FRONTEND__ROUTESCONFIG:hash'
                        ]
                    ],
                    'local_backend' => 'Cm_Cache_Backend_File',
                    'local_backend_options' => [
                        'cache_dir' => '/dev/shm/'
                    ]
                ],
                'frontend_options' => [
                    'write_control' => false
                ],
                'use_stale_cache' => true
            ],
            'page_cache' => [
                'id_prefix' => '061_'
            ]
        ],
        'type' => [
            'default' => [
                'frontend' => 'default'
            ]
        ],
        'allow_parallel_generation' => true
    ],

Caso você esteja usando ‘consumers‘ esta com problemas de CPU e Memoria, você pode querer desabilitar o ‘consumers_wait_for_messages’ na versão 2.4.1 em diante.

Exemplo de uma otimizaçao nesta configuração no env.php mesmo:

'cron_consumers_runner' => [
        'consumers_wait_for_messages' => 0,
        'cron_run' => true,
        'sleep' => 10,
        'max_messages' => 300
    ],
    'queue' => [
        'consumers_wait_for_messages' => 0,
        'amqp' => [
            'consumers_wait_for_messages' => 0,
            'host' => 'localhost',
            'port' => 5672,
            'user' => 'guest',
            'password' => 'guest',
            'virtualhost' => '/'
        ]
    ],

Isso fará com que os processo abertos fechem após a conclusão e não fiquem abertos em espera. Consulte a documentação oficial sobre o assunto: https://devdocs.magento.com/guides/v2.4/config-guide/mq/manage-message-queues.html.

Neste exemplo, estou usando RabbitMQ  https://devdocs.magento.com/guides/v2.4/install-gde/prereq/install-rabbitmq.html.

Quer saber mais sobre o RabbitMQ? O pessoal do Magenteiro criou um post completo sobre o assunto.

3 – Desativando módulos desnecessários. 

Alguns módulos são necessários para o Magento compilar corretamente, por ser dependência de algum outro módulo, porém você pode desabilitar alguns.

Exibindo os módulos instalados: php bin/magento module:status

Desativar um módulo específico, exemplo: php bin/magento module:disable Magento_Weee
Desativar vários de uma só vez, exemplo: php bin/magento module:disable -c {Klarna_Onsitemessaging,Klarna_Ordermanagement,Klarna_Kp,Klarna_Corer}

Argumento ‘-c‘ é o mesmo que –clear-static-content que como o nome já diz, força a limpeza dos arquivos estáticos gerados.

Dica, se você esta como usuário root ou outro diferente do usuário e grupo dos arquivos do Magento, por exemplo www-data que é o mais comum, o ideal é você colocar sudo -u www-data antes de qualquer  comando que for executar no magento-cli, por exemplo sudo -u www-data php bin/magento module:status. Essa é uma dica importante e irá evitar muitos erros de acessos negados em arquivos do Magento.

Uma lista de módulos que não uso por exemplo (Verifique se realmente não precisa deles, por exemplo Paypal):

sudo -u www-data php bin/magento module:disable -c {PayPal_BraintreeGraphQl,PayPal_Braintree,Magento_PaypalCaptcha,Magento_PaypalGraphQl,Magento_Paypal,Amazon_Login,Amazon_Payment,Amazon_Core,Magento_DownloadableImportExport,Magento_GroupedImportExport,Magento_InventoryBundleImportExport,Magento_BundleImportExport,Magento_TaxImportExport,Magento_SampleData,Magento_InstantPurchase}
sudo -u www-data php bin/magento module:disable -c {Magento_Csp,Magento_Fedex,Magento_Dhl,Magento_Ups,Magento_Usps,Magento_AdobeStockImageAdminUi,Magento_AdobeStockAdminUi,Magento_AdobeStockAssetApi,Magento_AdobeStockAsset,Magento_AdobeStockImageApi,Magento_AdobeStockImage,Magento_AdobeStockClientApi,Magento_AdobeStockClient,Magento_AdobeImsApi,Magento_AdobeIms}
sudo -u www-data php bin/magento module:disable -c {Klarna_Onsitemessaging,Klarna_Ordermanagement,Klarna_Kp,Klarna_Core,Magento_NewRelicReporting,Magento_CardinalCommerce,Magento_SendFriendGraphQl,Magento_SendFriend,Yotpo_Yotpo,Magento_TwoFactorAuth,Dotdigitalgroup_Chat,Dotdigitalgroup_Email,Vertex_AddressValidation,Vertex_Tax,Magento_WeeeGraphQl,Magento_Weee,Temando_ShippingRemover}
sudo -u www-data php bin/magento module:disable Magento_Persistent Magento_Elasticsearch6 Mageplaza_QuickFlushCache -c
sudo -u www-data php bin/magento module:disable Magento_Swagger Magento_SwaggerWebapi Magento_SwaggerWebapiAsync -c

Depois de desabilitar, não esqueça que precisa limpar cache, fazer o upgrade, deploy e recompilar como já mostrado na otimização do composer acima.

4 – Otimização do frontend com Megapack. https://github.com/magesuite/magepack.

Benefícios do Megapack (informado na documentção do modulo):

  1. Redução de até 98% nas solicitações de arquivo JavaScript. (Economia de solicitações https que podem gerar custos em alguns casos).
  2. Redução de até 44% no tamanho do JavaScript transferido.
  3. Redução de até 75% no tempo total de carregamento.
  4. Funciona com a “minificação” e “mesclagem” de JavaScript do Magento habilitadas.
  5. Usa solução customizada (inspirada em Baler) ao invés do otimizador RequireJs que é muito mais flexível, rápido, produz pacotes menores e não quebra com arquivos perdidos.

O Megapack não só reduz as solicitações, diminui os arquivos mas também faz otimização para evitar bloqueios, preload,  melhora o uso da CPU no frontend, resultando em um “Tempo de Interatividade” menor.  Atualmente uso em produção e tenho ficado satisfeito.

Irei mostrar a instalação feita no Ubuntu e Magento 2.4, então primeiro, instale as dependências:

Para instalação em outros sistemas, requisitos ou dúvidas sobre a instalação, consulte a documentação oficial: https://github.com/magesuite/magepack

apt-get install -y libxss1 libxss-dev
apt-get install -y libxcursor1 libxcursor-dev
apt-get install -y libgtk-3-0 libgtk-3-dev libgtk-3-bin libgtk-3-common
apt-get install -y npm

apt-get install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

#instalando megapack no ubuntu com npm
npm install -g magepack
#caso tenha dado algum erro, tente
npm install -g magepack --unsafe-perm=true
# em algumas instalações o chomium (puppeteer) não foi instalado corretamente então precisamos instalar
cd /usr/local/lib/node_modules/magepack 
npm install puppeteer
#caso tenha algum problema, tente
npm install puppeteer --save --unsafe-perm --allow-root


#Agora vamos instalar o módulo no Magento 2:
composer require creativestyle/magesuite-magepack

#limpe cache, faça o upgrade, deploy como informado na otimização do composer.

 

Agora que temos o megapack instalado no sistema e o modulo megapack instalado no Magento 2, vamos prosseguir. Certifique que neste momento a loja está funcionando, (produtos, categorias, checkout), você vai precisar ter a url de um produto, de uma categoria e de uma página cms qualquer.

Será preciso gerar o arquivo JavaScript otimizado, para fazer isso, troque exemplo.com pela url da sua loja, assim como no comando a seguir. Execute os próximos comandos na pasta raiz do Magento.

#Gerar arquivo otimizado ( 2 comandos ) e 1 alteração na configuração do Magento.
magepack generate --cms-url="http://exemplo.com:/uma-pagina-cms-qualquer" --category-url="http://exemplo.com/pagina-de-categoria" --product-url="http://exemplo.com/para-de-um-produto-seu"

#caso tenha dado algum erro de permissão do puppeteer, adicione o argumento no comando acima: -u httpUser

#finalmente, após execução completa do magepack generate, execute este comando:
magepack bundle

#Agora basta ativar o modulo no Magento para que seja carregado os arquivos otimizados.
sudo -u www-data bin/magento config:set dev/js/enable_magepack_js_bundling 1

#para recriar os arquivos otimizados, você precisa desabilitar a configuração acima, deixando o valor no final como 0 e para então depois você habilitar novamente com 1.
#Limpe o cache te teste. :)

Considerações finais.

Otimizando banco de dados, diminuindo as descrições de produtos com Blocos.
Otimizando alocação de memoria no MYSQL com Jemalloc
Otimização do Sistema, Rede e Arquivos: https://github.com/redati/magento2-ubuntu-dep/blob/main/Otimizar-Rede-Arquivos-Limites.txt
Otimização do Redis: https://github.com/redati/magento2-ubuntu-dep/blob/main/Otimizar-Redis.conf
Otimização do Varnish: https://github.com/redati/magento2-ubuntu-dep/blob/main/Otimizar-Varnish
Otimização do Mysql com ProxySql: Otimize as consultas e conexões com Proxysql.
Segurança: Bloquear acessos de hospedagens com Nginx, Geoip2 e ASN.
Conteúdo em desenvolvimento. ; )