Better Nginx rules for BWP Minify

The plugin Better WordPress Minify is a great plugin for handling CSS and JS merging and minification. I’ve been using it for years now but just noticed today that there’s a weird header being emitted on some of my sites.

Pragma: no-cache;

What!?! No, please cache!

Turns out it (probably) wasn’t BWP Minify in the first place. The sites that I was dealing with appear to be using PHP Sessions which caused that header to be kicked out.

But wait… BWP Minify is creating static CSS and JS files, what does PHP have to do with static files? That’s really weird.


Of course I’m running Nginx because I like to do things the hard way. After confirming that Nginx doesn’t just throw that header on for fun I started looking into the Nginx config rules that BWP Minify recommends. Right at the bottom was:

rewrite ^/wp-content/plugins/bwp-minify/cache/minify-b(\d+)-([a-zA-Z0-9-_.]+)\.(css|js)$ /index.php?blog=$1&min_group=$2&min_type=$3 last;

This rule tells Nginx to pass requests for static files in the cached directory back into WordPress. Once again, what!?!

I looked at the Apache rules and they appear to be the same.

The fix

Long story short, I’ve re-written the Nginx rules to use a `try_files` directive which will attempt to actually serve the files from disk if they exist. Also, as far as I could tell, the GZIP part wasn’t working either but is working in my version. Maybe there’s something I’m missing for why BWP Minify needs to handle each request but all I see is an overly expensive HTTP request.

#This is our global flag variable that must be set to ZCME below in
#order for GZIP support to kick in
set $minify_static "";

#If the client supports GZIP this will be set to ".gz"
set $zip_ext "";

#See if the client supports GZIP
if ($http_accept_encoding ~* gzip) {
    set $minify_static "${minify_static}Z";
    set $zip_ext ".gz";

#If we don't have a cache control set by the client (or some other config)
if ($http_cache_control = false) {
    set $minify_static "${minify_static}C";
    set $http_cache_control "";

#There's a cache control but it isn't set to "no-cache"
if ($http_cache_control !~* no-cache) {
    set $minify_static "${minify_static}C";

#If there's no "if modified since" header sent
if ($http_if_modified_since = false) {
    set $minify_static "${minify_static}M";

#If the file actually exists on disk
if (-f $request_filename$zip_ext) {
    set $minify_static "${minify_static}E";

#If all flags above were set
if ($minify_static = ZCME) {

    #Change the URL to pretend that a gzipped file was requested
    #The "last" directive tells nginx to re-scan all location blocks
    rewrite (.*) $1$zip_ext last;

#Handle everything within the cache folder
location ~ /wp-content/plugins/bwp-minify/cache/minify-b(\d+)-([a-zA-Z0-9\-_\.]+)\.(css|js|gz)$ {

    #Global headers that we'll always set
    add_header Cache-Control "public, max-age=86400";
    add_header Vary "Accept-Encoding";
    add_header Here 'Yes';
    etag off;
    expires max;

    #If the request is for a gzip file
    location ~ /wp-content/plugins/bwp-minify/cache/.*\.gz$ {

        #Disable gzip since this file is already compressed
        gzip off;

        #Erase the known type array, we'll pass a default later
        types {}

        #Manually sent the compressed header
        add_header Content-Encoding gzip;

        #JS files
        location ~ /wp-content/plugins/bwp-minify/cache/minify-b(\d+)-([a-zA-Z0-9\-_\.]+)\.(js)\.gz$ {
            default_type application/x-javascript;
            try_files $uri /index.php?blog=$1&min_group=$2&min_type=$3;

        #CSS Files
        location ~ /wp-content/plugins/bwp-minify/cache/minify-b(\d+)-([a-zA-Z0-9\-_\.]+)\.(css)\.gz$ {
            default_type text/css;
            try_files $uri /index.php?blog=$1&min_group=$2&min_type=$3;

    #For everything in this block, try the file on disk and if that doesn't work
    #pass it into WordPress for BWP to handle
    try_files $uri /index.php?blog=$1&min_group=$2&min_type=$3;

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.