Angular SSR Applikation mit nginx als reverse proxy und gzip Kompression

Server Side Rendering (SSR) mit Angular ermöglicht es, Anwendungen auf dem Server zu rendern und dann als HTML an den Client zu senden. Dies bietet Vorteile in Bezug auf die Suchmaschinenoptimierung und die Performance der Anwendung. Im Bezug auf die Konfiguration gibt es aber Unterschiede, insbesondere wenn nginx als reverse Proxy zum Einsatz kommt.

Wird die Angular Applikation direkt über den nginx-Server ausgeliefert, dann reicht eine einfache Konfiguration über die gzip_static Direktive direkt im nginx:

server {
  ...
  gzip_static on;
  gzip_proxied any;
  gzip_vary on;
  gunzip on;
  gzip_types application/javascript
  ...
}
Die beim Build generierten JavaScript Dateien können wir auch direkt mit gzip komprimieren (Auszug aus der package.json):
"scripts": {
    "gzip": "gzip --keep --recursive ./dist/browser/*.js",
    "build:de": "ng build --configuration=production ng run app-web:server:production && npm run gzip"
  }

Dient nginx aber nur als reverse proxy mit proxy_pass, dann ist die nginx-Konfiguration mit gzip_static unnötig und wir müssen direkt den Express Server von Angular bemühen. Hier die relevante Änderung in server.ts, die standardmäßig beim Hinzufügen von Server-Side Rendering (SSR) zu Angular erstellt wird:

export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/browser');

  server.get('*.js', (req, res, next) => {
    if (!existsSync(`${distFolder}${req.url}.gz`) || 
        req.headers['x-no-compression'] || 
        !req.header('Accept-Encoding').includes('gzip')) {
      return next();
    }
    req.url = `${req.url}.gz`;
    res.set({
      'Content-Type': 'text/javascript',
      'Content-Encoding': 'gzip',
      'Vary': 'Accept-Encoding',
      'Cache-Control': 'max-age=31536000'
    });
    next();
  });

}

Wir setzen hier voraus, dass die JavaScript Dateien im Build schon gzip-t wurden und sich im gleichen Verzeichnis wie die eigentliche JavaScript Datei befinden (beim zuvor gezeigtem Script aus der package.json passiert genau das).

Wenn ein GET-Request (server.get(...)) für eine JavaScript-Datei (*.js) eingeht, werden zunächst die erforderlichen Bedingungen überprüft, um festzustellen, ob die Datei ausgeliefert werden kann. Wenn die Bedingungen erfüllt sind, wird die Datei mit den entsprechenden Headern zurückgegeben:

Kurze Erläuterung zu den Response-Headern: