Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JeroenBoersma/6ece510192ce4292c79d010284544c56 to your computer and use it in GitHub Desktop.
Save JeroenBoersma/6ece510192ce4292c79d010284544c56 to your computer and use it in GitHub Desktop.
NGINX - Magento 2 Static files optimization

Introduction

Because Varnish doesn't support SSL, most people choose a setup where Nginx SSL will forward all traffic to Varnish and Varnish will forward will forward the traffic it cannot handle back to nginx. Or worse, bind Varnish on port 80 and direct all traffic into Varnish. This will already degrade performance, because Varnish will purge more because static files are also taking up room in the cache.

Default configuration

Next up, the Nginx configuration of Magento will handle static files.

The part which is related to static file handling.

# ...
location /static/ {
    # Uncomment the following line in production mode
    # expires max;

    # Remove signature of the static files that is used to overcome the browser cache
    location ~ ^/static/version\d*/ {
        rewrite ^/static/version\d*/(.*)$ /static/$1 last;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|svgz|webp|avif|avifs|js|css|eot|ttf|otf|woff|woff2|html|json|webmanifest)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1y;

        if (!-f $request_filename) {
            rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        expires    off;

        if (!-f $request_filename) {
           rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }
    if (!-f $request_filename) {
        rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
    }
    add_header X-Frame-Options "SAMEORIGIN";
}
# ...

Explanation

Take a request to /static/frontend/version12324354/Vendor/theme/language/path.to.file.something

  • remove the stamp from the url /static/frontend/Vendor/theme/language/path.to.file.something
  • if a file exist, serve it
  • if it is not found, forward it to static.php
  • add some correct headers for several content types

static.php will handle the fallback system when doing compact mode, seperate topic, this will work for the quick mode. Will update later for compact strategy.

This creates needless overhead and cache misses.

Solution

We can disable and static.php for static content lookup and bypass Varnish by adding the next lines in NGINX on the SSL server in the server section.

location /static {
  expires max;

  # Remove signature of the static files that is used to overcome the browser cache
  location ~ ^/static/version {
    rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
  }

  add_header Cache-Control "public";
  add_header X-Frame-Options "SAMEORIGIN";

  allow all;
}

Example before/after

Request: /static/frontend/version12324354/Vendor/theme/language/path.to.file.something

before

  • NGINX (SSL)
  • Varnish
  • NGINX (backend)
  • PHP
  • result 404/200

after

  • NGINX (SSL)
  • result 404/200

Special thanks to MageUnconf22

We were discussing static file optimization for production. I opt this solution in the believing I already shared this before. We were already running this for years and thought this gist already existed, but I was wrong. I think I shared it somewhere else sometime ago and got lost in history.

So here it is for the long lasting future. With love for the Magento Community ❤️

Todo

Add Nginx tip when using bin/magento static:content:deploy --strategy=compact and implement the fallback system in Nginx.

@JeroenBoersma
Copy link
Author

Compact strategy

This is how the fallback for a compact strategy can be managed in Nginx instead of PHP (pub/static.php)...

# do the fallback system if the fallback system of Magento fails
location ~* /static/frontend/(?<t_theme>[^/]*/[^/]*)/(?<t_lang>[^/]*)/(?<t_file>.*)$ {

  add_header Pragma public;
  add_header Cache-Control "public";
  expires +1y;

  if ($t_file ~ .css$) {
    add_header X-Content-Type-Options nosniff;
    add_header Content-Type "text/css";
  }

  if ($t_file ~ .js$) {
    add_header X-Content-Type-Options nosniff;
    add_header Content-Type "text/javascript";
  }

  # fallback via themes / reset / default
  try_files $request_filename
            /static/frontend/$t_theme/$t_lang/$t_file
            /static/frontend/$t_theme/default/$t_file

            /static/frontend/Hyva/reset/$t_lang/$t_file
            /static/frontend/Hyva/reset/default/$t_file

            /static/frontend/Magento/base/default/$t_file

            =404;

  allow all;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment