/magento2-performance-optimizations

Magento 2 performance optimizations aimed for developers actively developing for Magento 2

Magento 2 performance optimizations

Magento 2 performance optimizations aimed for developers actively developing for Magento 2

The idea is to run Magento 2 in production mode for performance, but make adjustments to it so that it does not need to be recompiled and the static files do not need to be redeployed with every change. Additionally, some further adjustments will be necessary to display debugging errors and allow symlinks for module development.

  • Increase error verbosity #1:
diff --git a/app/bootstrap.php b/app/bootstrap.php
index 6701a9f..fac9b82 100644
--- a/app/bootstrap.php
+++ b/app/bootstrap.php
@@ -8,7 +8,7 @@
  * Environment initialization
  */
 error_reporting(E_ALL);
-#ini_set('display_errors', 1);
+ini_set('display_errors', 1);
 
 /* PHP version validation */
 if (!defined('PHP_VERSION_ID') || !(PHP_VERSION_ID === 70002 || PHP_VERSION_ID === 70004 || PHP_VERSION_ID >= 70006)) {
  • Increase error verbosity #2:
diff --git a/pub/errors/processor.php b/pub/errors/processor.php
index 5ca9d82..ee32424 100644
--- a/pub/errors/processor.php
+++ b/pub/errors/processor.php
@@ -332,7 +332,7 @@ class Processor
 
         //initial settings
         $config = new \stdClass();
-        $config->action         = '';
+        $config->action         = 'print';
         $config->subject        = 'Store Debug Information';
         $config->email_address  = '';
         $config->trash          = 'leave';
  • Increase error verbosity #3:
diff --git a/vendor/magento/framework/Webapi/ErrorProcessor.php b/vendor/magento/framework/Webapi/ErrorProcessor.php
index bb86c6b..edc1f97 100644
--- a/vendor/magento/framework/Webapi/ErrorProcessor.php
+++ b/vendor/magento/framework/Webapi/ErrorProcessor.php
@@ -108,7 +108,7 @@ class ErrorProcessor
      */
     public function maskException(\Exception $exception)
     {
-        $isDevMode = $this->_appState->getMode() === State::MODE_DEVELOPER;
+        $isDevMode = true;//$this->_appState->getMode() === State::MODE_DEVELOPER;
         $stackTrace = $isDevMode ? $exception->getTraceAsString() : null;
 
         if ($exception instanceof WebapiException) {
  • Increase error verbosity #4:
diff --git a/vendor/magento/framework/App/StaticResource.php b/vendor/magento/framework/App/StaticResource.php
index 87a2c37..a4ee009 100644
--- a/vendor/magento/framework/App/StaticResource.php
+++ b/vendor/magento/framework/App/StaticResource.php
@@ -143,7 +143,7 @@ class StaticResource implements \Magento\Framework\AppInterface
     public function catchException(Bootstrap $bootstrap, \Exception $exception)
     {
         $this->getLogger()->critical($exception->getMessage());
-        if ($bootstrap->isDeveloperMode()) {
+        if (true || $bootstrap->isDeveloperMode()) {
             $this->response->setHttpResponseCode(404);
             $this->response->setHeader('Content-Type', 'text/plain');
             $this->response->setBody($exception->getMessage() . "\n" . $exception->getTraceAsString());
  • When we deploy static assets, instead of copying the files, symlink them instead to the originals, so that we do not need to re-deploy them while we are developing the modules:
diff --git a/app/etc/di.xml b/app/etc/di.xml
index e17505e..193d166 100644
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -643,7 +643,8 @@
         <arguments>
             <argument name="strategiesList" xsi:type="array">
                 <item name="view_preprocessed" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink</item>
-                <item name="default" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Copy</item>
+                <item name="default" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink</item>
+                <item name="asset" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Copy</item>
             </argument>
         </arguments>
     </virtualType>
  • Because we will be using symlinks, we now have to adjust Magento to skip file validation which is normally there for security purposes (i.e. don't do anything stupid on an actual live server). This will also allow us to use modman to symlink modules into the codebase.
diff --git a/vendor/magento/framework/View/Element/Template/File/Validator.php b/vendor/magento/framework/View/Element/Template/File/Validator.php
index 4b4e7e1..8dc7a5f 100644
--- a/vendor/magento/framework/View/Element/Template/File/Validator.php
+++ b/vendor/magento/framework/View/Element/Template/File/Validator.php
@@ -103,6 +103,7 @@ class Validator
      */
     public function isValid($filename)
     {
+        return true;
         $filename = str_replace('\\', '/', $filename);
         if (!isset($this->_templatesValidationResults[$filename])) {
             $this->_templatesValidationResults[$filename] =
  • Magento 2.3 specific symlinks adjustment
diff --git a/vendor/magento/framework/Filesystem/Directory/PathValidator.php b/vendor/magento/framework/Filesystem/Directory/PathValidator.php
index fe0e6b3..d3b4b39 100644
--- a/vendor/magento/framework/Filesystem/Directory/PathValidator.php
+++ b/vendor/magento/framework/Filesystem/Directory/PathValidator.php
@@ -41,6 +41,7 @@ class PathValidator implements PathValidatorInterface
         ?string $scheme = null,
         bool $absolutePath = false
     ): void {
+        return;
         $realDirectoryPath = $this->driver->getRealPathSafety($directoryPath);
         if ($realDirectoryPath[-1] !== DIRECTORY_SEPARATOR) {
             $realDirectoryPath .= DIRECTORY_SEPARATOR;
  • Also because we are not redeploying the assets, have magento generate them on the fly without refering to a deployment version:
diff --git a/vendor/magento/framework/App/View/Deployment/Version.php b/vendor/magento/framework/App/View/Deployment/Version.php
index 67f6d3c..393a242 100644
--- a/vendor/magento/framework/App/View/Deployment/Version.php
+++ b/vendor/magento/framework/App/View/Deployment/Version.php
@@ -79,7 +79,7 @@ class Version
     {
         $result = $this->versionStorage->load();
         if (!$result) {
-            if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION
+            if (false && $appMode == \Magento\Framework\App\State::MODE_PRODUCTION
                 && !$this->deploymentConfig->getConfigData(
                     ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION
                 )
  • and
diff --git a/vendor/magento/framework/App/StaticResource.php b/vendor/magento/framework/App/StaticResource.php
index 87a2c37..2871dca 100644
--- a/vendor/magento/framework/App/StaticResource.php
+++ b/vendor/magento/framework/App/StaticResource.php
@@ -116,7 +116,7 @@ class StaticResource implements \Magento\Framework\AppInterface
     {
         // disabling profiling when retrieving static resource
         \Magento\Framework\Profiler::reset();
-        $appMode = $this->state->getMode();
+        $appMode = \Magento\Framework\App\State::MODE_DEVELOPER; // $this->state->getMode();
         if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION
             && !$this->deploymentConfig->getConfigData(
                 ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION
  • This approach will require a cache clean when an xml file is changed or when an admin config changes, so a command line method of quickly cleaning the cache would be nice:

alias c='php bin/magento cache:clean'

  • You probably also want your nginx web server (you are using nginx, right?) to cache the Magento assets, but not the assets from your own modules, so turn off browser caching for http requests that include the name of your module:
    location ~* ^.*(cryozonic|payments|crypto).*\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|html)$ {
        expires off;
        add_header Cache-Control "no-cache";
        add_header X-Frame-Options "SAMEORIGIN";

        if (!-f $request_filename) {
            rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }

Hit it:

php bin/magento setup:upgrade
php bin/magento deploy:mode:set production
php bin/magento setup:config:set --enable-debug-logging=true
php bin/magento cache:enable
php bin/magento cache:flush
rm -rf generated/*
rm -rf var/generation/*
rm -rf var/di/*

Now if someone could put the above into a Magento 2 module...