Nginx config with some conditionals This config has 3 main features but there seems to be a lot of duplication and I wonder if I could improve it.

1 Detect all pngs and jpgs in static/img and try a webp version if the requesting browser supports it

2 Detect non-ES6 supporting browsers and serve site.babel.js, otherwise serve site.js which is un-babelified

3 Proxy all other requests to a node app running on port 3000

upstream node_upstream {
    server node:3000;
    keepalive 64;
}

#Required since SSL termination is higher up at the AWS load balancer
map $http_x_forwarded_proto $is_https {
  default off;
  https on;
}

map $http_accept $webp_suffix {
    default   "";
    "~*webp"  ".webp";
}

map $http_user_agent $script_file {
    default                                 "site.js";
    "~MSIE"                                 "site.babel.js";
    "~Trident"                              "site.babel.js";
    "~Opera.*Version/[0-9]\."               "site.babel.js";
    "~Opera.*Version/[0-1][0-9]\."          "site.babel.js";
    "~Opera.*Version/2[0-1]\."              "site.babel.js";
    "~AppleWebKit.*Version/[0-9]\..*Safari" "site.babel.js";
    "~Chrome/[0-9]\."                       "site.babel.js";
    "~Chrome/[0-2][0-9]\."                  "site.babel.js";
    "~Chrome/3[0-3]\."                      "site.babel.js";
    "~Chrome/4[0-3]\."                      "site.babel.js";
    "~Edge/1[0-3]\."                        "site.babel.js";
}

server {
    root /var/www/html/src;

    gzip on;

    # AWS traffic will come via a load balancer with the original protocol stored in http_x_forwarded_proto
    # If this is set to http then we need to redirect any request onto https equivalent
    # Should be ignored in non AWS environment as http_x_forwarded_proto should not be set
    if ($http_x_forwarded_proto = "http") {
      rewrite ^(.*)$ https://$http_host$1 permanent;
    }

    location = /static/site.js {
        root  /var/www/html/src;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
        try_files /static/$script_file =404;
    }

    location ~* ^/static/img/.+\.(png|jpg)$ {
        root /var/www/html/src;
        add_header Vary Accept;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
        try_files $uri$webp_suffix $uri =404;
    }

    location ~* ^/static/.*$
    {
        root  /var/www/html/src;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
    }

    location / {
        proxy_redirect off;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   Host                   $http_host;
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;
        proxy_pass         http://node_upstream;
    }

    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
}
root

The root directive is inherited. You have the same statement in the server block, and repeated in a number of location blocks. Only the first statement is necessary. See this document for details.

location ~* ^/static/.*$

This can be replaced by the prefix location:

location /static/ { ... }


The prefix location is more efficient than the regular expression location. The precedence order is different, but that does not affect your current configuration. See this document for details.

rewrite ^(.*)$ https://$http_host$1 permanent;

You can replace this with a return statement, thus eliminating a regular expression.

return 301 https://$http_host$request_uri;


Nested location blocks

A number of statements are common to three location blocks, all of which represent URIs that begin with /static/. The expires, access_log and add_header directives are inherited.

You could restructure your locations as follows:

location /static/ {
    root  /var/www/html/src;
    expires 1y;
    access_log off;
    add_header Cache-Control "public";

    location = /static/site.js {
        try_files /static/$script_file =404;
    }
    location ~* ^/static/img/.+\.(png|jpg)$ {
        add_header Vary Accept;
        add_header Cache-Control "public";
        try_files $uri$webp_suffix $uri =404;
    }
}
location / {
    ...
}


This would improve efficiency as URIs which do not begin with /static/ will not need to be checked against the regular expressions.

The add_header directive has an additional inheritance rule. See this document for details.