└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 performance optimizations 2 | 3 | Magento 2 performance optimizations aimed for developers actively developing for Magento 2 4 | 5 | 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. 6 | 7 | - [ ] Increase error verbosity #1: 8 | 9 | ```patch 10 | diff --git a/app/bootstrap.php b/app/bootstrap.php 11 | index 6701a9f..fac9b82 100644 12 | --- a/app/bootstrap.php 13 | +++ b/app/bootstrap.php 14 | @@ -8,7 +8,7 @@ 15 | * Environment initialization 16 | */ 17 | error_reporting(E_ALL); 18 | -#ini_set('display_errors', 1); 19 | +ini_set('display_errors', 1); 20 | 21 | /* PHP version validation */ 22 | if (!defined('PHP_VERSION_ID') || !(PHP_VERSION_ID === 70002 || PHP_VERSION_ID === 70004 || PHP_VERSION_ID >= 70006)) { 23 | ``` 24 | 25 | - [ ] Increase error verbosity #2: 26 | 27 | ```patch 28 | diff --git a/pub/errors/processor.php b/pub/errors/processor.php 29 | index 5ca9d82..ee32424 100644 30 | --- a/pub/errors/processor.php 31 | +++ b/pub/errors/processor.php 32 | @@ -332,7 +332,7 @@ class Processor 33 | 34 | //initial settings 35 | $config = new \stdClass(); 36 | - $config->action = ''; 37 | + $config->action = 'print'; 38 | $config->subject = 'Store Debug Information'; 39 | $config->email_address = ''; 40 | $config->trash = 'leave'; 41 | ``` 42 | 43 | - [ ] Increase error verbosity #3: 44 | 45 | ```patch 46 | diff --git a/vendor/magento/framework/Webapi/ErrorProcessor.php b/vendor/magento/framework/Webapi/ErrorProcessor.php 47 | index bb86c6b..edc1f97 100644 48 | --- a/vendor/magento/framework/Webapi/ErrorProcessor.php 49 | +++ b/vendor/magento/framework/Webapi/ErrorProcessor.php 50 | @@ -108,7 +108,7 @@ class ErrorProcessor 51 | */ 52 | public function maskException(\Exception $exception) 53 | { 54 | - $isDevMode = $this->_appState->getMode() === State::MODE_DEVELOPER; 55 | + $isDevMode = true;//$this->_appState->getMode() === State::MODE_DEVELOPER; 56 | $stackTrace = $isDevMode ? $exception->getTraceAsString() : null; 57 | 58 | if ($exception instanceof WebapiException) { 59 | ``` 60 | 61 | - [ ] Increase error verbosity #4: 62 | 63 | ```patch 64 | diff --git a/vendor/magento/framework/App/StaticResource.php b/vendor/magento/framework/App/StaticResource.php 65 | index 87a2c37..a4ee009 100644 66 | --- a/vendor/magento/framework/App/StaticResource.php 67 | +++ b/vendor/magento/framework/App/StaticResource.php 68 | @@ -143,7 +143,7 @@ class StaticResource implements \Magento\Framework\AppInterface 69 | public function catchException(Bootstrap $bootstrap, \Exception $exception) 70 | { 71 | $this->getLogger()->critical($exception->getMessage()); 72 | - if ($bootstrap->isDeveloperMode()) { 73 | + if (true || $bootstrap->isDeveloperMode()) { 74 | $this->response->setHttpResponseCode(404); 75 | $this->response->setHeader('Content-Type', 'text/plain'); 76 | $this->response->setBody($exception->getMessage() . "\n" . $exception->getTraceAsString()); 77 | ``` 78 | 79 | - [ ] 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: 80 | 81 | ```patch 82 | diff --git a/app/etc/di.xml b/app/etc/di.xml 83 | index e17505e..193d166 100644 84 | --- a/app/etc/di.xml 85 | +++ b/app/etc/di.xml 86 | @@ -643,7 +643,8 @@ 87 | 88 | 89 | Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink 90 | - Magento\Framework\App\View\Asset\MaterializationStrategy\Copy 91 | + Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink 92 | + Magento\Framework\App\View\Asset\MaterializationStrategy\Copy 93 | 94 | 95 | 96 | ``` 97 | 98 | - [ ] 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. 99 | 100 | ```patch 101 | diff --git a/vendor/magento/framework/View/Element/Template/File/Validator.php b/vendor/magento/framework/View/Element/Template/File/Validator.php 102 | index 4b4e7e1..8dc7a5f 100644 103 | --- a/vendor/magento/framework/View/Element/Template/File/Validator.php 104 | +++ b/vendor/magento/framework/View/Element/Template/File/Validator.php 105 | @@ -103,6 +103,7 @@ class Validator 106 | */ 107 | public function isValid($filename) 108 | { 109 | + return true; 110 | $filename = str_replace('\\', '/', $filename); 111 | if (!isset($this->_templatesValidationResults[$filename])) { 112 | $this->_templatesValidationResults[$filename] = 113 | ``` 114 | 115 | - [ ] Magento 2.3 specific symlinks adjustment 116 | 117 | ```patch 118 | diff --git a/vendor/magento/framework/Filesystem/Directory/PathValidator.php b/vendor/magento/framework/Filesystem/Directory/PathValidator.php 119 | index fe0e6b3..d3b4b39 100644 120 | --- a/vendor/magento/framework/Filesystem/Directory/PathValidator.php 121 | +++ b/vendor/magento/framework/Filesystem/Directory/PathValidator.php 122 | @@ -41,6 +41,7 @@ class PathValidator implements PathValidatorInterface 123 | ?string $scheme = null, 124 | bool $absolutePath = false 125 | ): void { 126 | + return; 127 | $realDirectoryPath = $this->driver->getRealPathSafety($directoryPath); 128 | if ($realDirectoryPath[-1] !== DIRECTORY_SEPARATOR) { 129 | $realDirectoryPath .= DIRECTORY_SEPARATOR; 130 | ``` 131 | 132 | - [ ] Also because we are not redeploying the assets, have magento generate them on the fly without refering to a deployment version: 133 | 134 | ```patch 135 | diff --git a/vendor/magento/framework/App/View/Deployment/Version.php b/vendor/magento/framework/App/View/Deployment/Version.php 136 | index 67f6d3c..393a242 100644 137 | --- a/vendor/magento/framework/App/View/Deployment/Version.php 138 | +++ b/vendor/magento/framework/App/View/Deployment/Version.php 139 | @@ -79,7 +79,7 @@ class Version 140 | { 141 | $result = $this->versionStorage->load(); 142 | if (!$result) { 143 | - if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION 144 | + if (false && $appMode == \Magento\Framework\App\State::MODE_PRODUCTION 145 | && !$this->deploymentConfig->getConfigData( 146 | ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION 147 | ) 148 | ``` 149 | 150 | - [ ] and 151 | 152 | 153 | ```patch 154 | diff --git a/vendor/magento/framework/App/StaticResource.php b/vendor/magento/framework/App/StaticResource.php 155 | index 87a2c37..2871dca 100644 156 | --- a/vendor/magento/framework/App/StaticResource.php 157 | +++ b/vendor/magento/framework/App/StaticResource.php 158 | @@ -116,7 +116,7 @@ class StaticResource implements \Magento\Framework\AppInterface 159 | { 160 | // disabling profiling when retrieving static resource 161 | \Magento\Framework\Profiler::reset(); 162 | - $appMode = $this->state->getMode(); 163 | + $appMode = \Magento\Framework\App\State::MODE_DEVELOPER; // $this->state->getMode(); 164 | if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION 165 | && !$this->deploymentConfig->getConfigData( 166 | ConfigOptionsListConstants::CONFIG_PATH_SCD_ON_DEMAND_IN_PRODUCTION 167 | ``` 168 | 169 | - [ ] 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: 170 | 171 | `alias c='php bin/magento cache:clean'` 172 | 173 | - [ ] 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: 174 | 175 | ```nginx 176 | location ~* ^.*(cryozonic|payments|crypto).*\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|html)$ { 177 | expires off; 178 | add_header Cache-Control "no-cache"; 179 | add_header X-Frame-Options "SAMEORIGIN"; 180 | 181 | if (!-f $request_filename) { 182 | rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; 183 | } 184 | } 185 | ``` 186 | 187 | Hit it: 188 | 189 | ```bash 190 | php bin/magento setup:upgrade 191 | php bin/magento deploy:mode:set production 192 | php bin/magento setup:config:set --enable-debug-logging=true 193 | php bin/magento cache:enable 194 | php bin/magento cache:flush 195 | rm -rf generated/* 196 | rm -rf var/generation/* 197 | rm -rf var/di/* 198 | ``` 199 | 200 | Now if someone could put the above into a Magento 2 module... 201 | 202 | --------------------------------------------------------------------------------