Enable Brotli Compression in Nginx for Faster Asset Delivery
How to configure Brotli compression in Nginx to reduce transfer sizes for JavaScript, CSS, and HTML assets with better ratios than Gzip
Note: This guide follows English-language naming conventions and terminology standards common in international development teams. Examples use English identifiers and comments to maximize compatibility across codebases and tooling.
Enable Brotli Compression in Nginx for Faster Asset Delivery
Brotli is a modern compression algorithm developed by Google that consistently achieves 15-25% smaller file sizes than Gzip for text-based assets. When combined with Nginx and proper content-type configuration, it reduces bandwidth usage and improves page load times for all users.
When to Use This
- You serve static assets through Nginx and want maximum compression
- Your users are on modern browsers that support Brotli (95%+ coverage)
- Bandwidth costs are a significant factor in infrastructure spend
Prerequisites
- Nginx compiled with the
ngx_brotlimodule or using thenginx-fullpackage - SSL/TLS certificate (Brotli is only effective over HTTPS in practice)
Solution
1. Install the Brotli Module
# Ubuntu/Debian with precompiled module
sudo apt install nginx-extras
# Or compile from source
./configure \
--with-compat \
--add-dynamic-module=/path/to/ngx_brotli
make && sudo make install
2. Configure Brotli in Nginx
# /etc/nginx/nginx.conf
http {
# Load the dynamic module if compiled dynamically
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
# Enable dynamic Brotli compression
brotli on;
brotli_comp_level 6;
brotli_types
text/plain
text/css
text/xml
application/javascript
application/json
application/xml
image/svg+xml
font/woff2;
# Pre-compressed static files (optional)
brotli_static on;
}
3. Pre-Compress Static Assets at Build Time
# Build script for CI/CD
for file in dist/**/*.{js,css,html,svg}; do
if [ -f "$file" ]; then
brotli --quality=11 --output="${file}.br" "$file"
fi
done
// vite-plugin-brotli.js
import { brotliCompressSync } from 'zlib';
import { readFileSync, writeFileSync } from 'fs';
import { resolve } from 'path';
export default function brotliPlugin() {
return {
name: 'brotli',
closeBundle() {
const dist = resolve('dist');
const files = ['.js', '.css', '.html', '.svg'];
files.forEach(ext => {
const file = resolve(dist, `index${ext}`);
try {
const compressed = brotliCompressSync(readFileSync(file));
writeFileSync(`${file}.br`, compressed);
} catch { /* file does not exist */ }
});
}
};
}
4. Verify Compression is Working
# Check response headers
curl -H "Accept-Encoding: br" -I https://example.com/app.js
# Expected output
HTTP/2 200
content-encoding: br
content-type: application/javascript
5. Fallback to Gzip for Older Clients
server {
location ~ \.(js|css|html|svg)$ {
# Nginx automatically negotiates encoding based on Accept-Encoding header
# Brotli takes priority when both are supported
gzip on;
gzip_types text/plain text/css application/javascript;
gzip_vary on;
}
}
How It Works
- Brotli Algorithm uses a dictionary-based approach optimized for web content
- Dynamic Compression compresses responses on-the-fly for uncached content
- Static Pre-Compression serves pre-built
.brfiles to avoid CPU overhead - Content Negotiation Nginx selects Brotli or Gzip based on the
Accept-Encodingheader
Production Considerations
- Use compression level 4-6 for dynamic content; level 11 for pre-compressed static assets
- Monitor CPU usage; Brotli at high levels can be CPU-intensive
- Combine with a CDN that supports Brotli caching for maximum benefit
- Test with WebPageTest or Lighthouse to verify transfer size reductions
Common Mistakes
- Forgetting to add
font/woff2tobrotli_types; WOFF2 fonts compress well - Using
brotli_comp_level 11for dynamic content, causing high latency - Not enabling
brotli_staticand compressing the same files on every request
FAQ
Q: Should I replace Gzip entirely with Brotli? A: No. Serve Brotli to modern browsers and Gzip as a fallback for older clients.
Q: Does Brotli help with images? A: Minimal benefit for already-compressed formats like JPEG and PNG. Use it for SVG, JSON, and JavaScript.
Q: How much smaller is Brotli compared to Gzip? A: Typically 15-25% smaller for JavaScript and CSS. HTML sees 10-15% improvement.
Related Resources
Compress and Decompress Files with Gzip and Brotli
How to reduce file sizes for APIs, static assets, and log files using Gzip, Brotli, and zlib with streaming compression, content negotiation, and best practices.
RecipeImplement CDN Edge Caching
Configure content delivery networks with edge caching rules, cache invalidation, and geographic optimization for static and dynamic content.
GuideWeb Performance Optimization Guide
A comprehensive guide to optimizing web application performance for better Core Web Vitals and user experience.