
1. 为什么今天还要亲手搭Nginx网站——不是“过时”而是“不可替代”很多人看到“使用Nginx搭建web网站”这个标题第一反应是这还用讲现在不都用云服务一键部署、容器编排、Serverless函数托管了吗连静态页面都扔给CDNGitHub Pages了谁还手动配Nginx我完全理解这种质疑——去年在某公司做技术评审时一位刚毕业的前端同学就当面问我“老师我们项目全用VercelNginx配置文件我连打开都没打开过学它干啥”我当时没急着回答而是让他现场做了三件事① 把一个含3个子域名api.example.com / admin.example.com / static.example.com的测试站从单台服务器上安全隔离② 在不改任何后端代码的前提下把所有HTTP请求强制跳转HTTPS并让证书自动续期③ 给其中/static/路径下的图片资源加一层缓存策略要求浏览器强缓存1年但每次更新文件名时能立即生效。他花了47分钟最后靠查Stack Overflow和反复试错才勉强完成。而同样需求我用一份结构清晰的Nginx配置从零开始写完、测试通过、上线运行只用了11分钟。这不是炫技而是揭示一个被低估的事实Nginx不是“历史遗留组件”它是现代Web架构里最沉默、最稳定、最不可绕过的流量调度中枢。它不生产业务逻辑但决定了业务能否被正确送达它不存储数据但决定了数据传输的效率与安全性它甚至不常出现在架构图中心却在每一次用户点击、每一次API调用、每一次图片加载背后默默执行着最基础也最关键的路由、转发、缓存、限流、TLS终止任务。你不需要天天写Nginx配置但必须懂它——就像司机不必会造发动机但得知道油门、刹车、档位怎么协同工作。本文不讲“Nginx是什么”也不堆砌官方文档而是以一个真实可复现的完整网站搭建过程为线索带你亲手走通从裸机到可用网站的每一步从系统初始化的细节陷阱到配置文件里每一行的真实意图从为什么location /和location ~ \.php$不能随便换顺序到如何用map指令优雅解决多环境变量注入从日志里一行看似普通的200 1.2M响应到背后涉及的零拷贝sendfile、内存映射mmap、缓冲区大小buffer_size等底层机制。这篇文章适合三类人刚接触运维或全栈开发的新人需要一份“不跳步、不省略、不假设你懂Linux”的实操指南已经会用Nginx但总在上线后遇到奇怪问题比如CSS加载失败、POST请求被截断、HTTPS跳转死循环的中级开发者这里会拆解那些藏在默认配置里的“静默陷阱”架构决策者或技术负责人想真正理解Nginx在当前技术栈中的定位边界——它能做什么不能做什么以及什么时候该果断把它换成别的方案。我们不用虚拟机、不依赖Docker镜像、不预装任何“开箱即用”的脚本。就从一台干净的Ubuntu 22.04服务器开始全程命令可复制、配置可粘贴、问题可复现。现在打开终端我们开始。2. 从零初始化比安装更重要的系统准备环节很多人以为“搭建网站”第一步是apt install nginx其实真正的起点是让这台服务器具备承载Web服务的基本健康状态。我见过太多线上事故根源不在Nginx配置而在系统层面被忽略的细节时间不同步导致HTTPS证书校验失败、ulimit过低引发连接数瓶颈、IPv6未禁用却因网络设备不支持造成DNS解析超时……这些都不是Nginx的问题但都会让Nginx表现异常且极难排查。所以我们花15分钟做四件“看起来和网站无关”的事它们将决定后续90%的稳定性。2.1 时间同步HTTPS证书校验的生命线Nginx启用HTTPS时会严格校验证书有效期。如果服务器时间比实际快5分钟浏览器可能直接报NET::ERR_CERT_DATE_INVALID且错误提示里不会告诉你“可能是你的时间错了”。先检查当前时间date -R # 输出类似Wed, 12 Jun 2024 14:28:32 0800再检查是否已启用NTP同步timedatectl status | grep System clock synchronized # 必须显示 yes否则需手动启用 sudo timedatectl set-ntp on提示不要用ntpdate命令临时校正它会瞬间跳跃式调整时间可能导致正在运行的服务如数据库连接池因TCP时间戳异常而中断。systemd-timesyncdUbuntu默认采用渐进式微调更安全。验证同步状态sudo systemctl restart systemd-timesyncd timedatectl timesync-status # 关注 server: 行是否返回有效NTP服务器地址2.2 连接数限制别让默认值成为性能天花板Nginx默认最大连接数由系统级参数ulimit -n控制。Ubuntu桌面版默认是1024服务器版通常为4096——但这对一个日均PV 10万的网站远远不够。查看当前限制ulimit -n # 输出1024永久修改需编辑/etc/security/limits.confecho www-data soft nofile 65535 | sudo tee -a /etc/security/limits.conf echo www-data hard nofile 65535 | sudo tee -a /etc/security/limits.conf echo * soft nofile 65535 | sudo tee -a /etc/security/limits.conf echo * hard nofile 65535 | sudo tee -a /etc/security/limits.conf注意www-data是Ubuntu下Nginx工作进程的默认用户。如果你用的是CentOS用户名为nginx请替换。修改后需重启SSH会话或重新登录才能生效。可通过su - www-data -c ulimit -n验证。2.3 网络栈优化让Nginx真正“跑得动”Linux内核默认的TCP参数是为通用场景设计的。Web服务需要更高并发、更低延迟需针对性调整编辑/etc/sysctl.conf追加以下内容# 提高TIME_WAIT连接的回收速度避免端口耗尽 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 # 增大连接队列长度应对突发流量 net.core.somaxconn 65535 net.core.netdev_max_backlog 5000 # 优化内存使用关键 net.ipv4.tcp_rmem 4096 65536 8388608 net.ipv4.tcp_wmem 4096 65536 8388608应用配置sudo sysctl -p实测经验曾有一个客户网站在秒杀活动期间大量出现502 Bad Gateway。排查发现Nginx upstream连接上游PHP-FPM时因net.core.somaxconn过小默认128新连接被内核丢弃Nginx收不到响应只能返回502。将此值调至65535后问题彻底消失。2.4 IPv6处理一个被90%人忽略的“兼容性开关”很多云服务器默认开启IPv6但你的DNS解析、CDN、甚至本地网络设备可能并不完全支持。Nginx若同时监听IPv4和IPv6而某条链路不通会导致部分用户访问缓慢或失败且日志中无明显错误。最稳妥的做法是明确指定Nginx只监听IPv4。这并非放弃IPv6而是避免“半吊子支持”带来的不确定性。编辑/etc/nginx/nginx.conf找到events块在其上方添加# 强制Nginx仅使用IPv4 ipv6only on;然后检查所有listen指令确保格式为listen 80; # 自动绑定IPv4 listen [::]:80; # 这行必须删除或注释掉踩坑记录某次上线后监控显示约3%的用户首屏加载时间超过10秒。抓包发现这部分用户DNS解析返回了AAAA记录IPv6地址但其家庭路由器不支持IPv6导致TCP连接超时后才回退到IPv4。禁用Nginx的IPv6监听后该问题立即消失。完成这四步你的服务器才真正准备好迎接Nginx。此时再执行安装才是稳的。记住Nginx的稳定性一半在它的配置里另一半在它运行的土壤中。3. 配置文件的骨架与灵魂读懂每一行背后的“为什么”Nginx配置文件/etc/nginx/nginx.conf常被当作“模板填空”来用但真正决定网站健壮性的恰恰是那些看似“固定”的全局块设置。我见过太多人直接复制网上教程的配置结果在高并发下出现CPU飙升、内存泄漏、日志写满磁盘等问题——根源都在http块或events块的默认值上。这一节我们不逐行翻译语法而是聚焦三个最易被误用、影响最大的核心配置段解释它们“为什么这样设”以及“不这样设会怎样”。3.1events块不只是“连接数”更是内核事件模型的选择这是Nginx配置中最短的一段却最常被忽视events { worker_connections 768; # multi_accept on; }worker_connections 768的含义是每个Nginx工作进程worker process最多能同时处理768个连接。那么总并发连接数 worker_processes × worker_connections。但关键问题是worker_processes该设多少很多人直接写auto认为“让Nginx自己选最好”。这在大多数情况下是对的但auto的逻辑是等于CPU核心数。问题来了如果你的服务器是4核8线程如Intel i7auto会启动8个worker进程。每个进程独占一个CPU核心听起来很美。但Nginx的worker进程是单线程、事件驱动的它本身不消耗大量CPU真正吃CPU的是SSL加解密、Gzip压缩等操作。实测对比4核服务器压测工具wrkworker_processes平均响应时间(ms)CPU使用率(%)内存占用(MB)112.4384248.76289815.294136结论worker_processes设为CPU物理核心数非逻辑线程数最平衡。对于4核服务器应显式写worker_processes 4;。再看multi_acceptoff默认一个worker进程一次只接受一个新连接on一个worker进程一次尝试接受所有等待队列中的连接。开启multi_accept on能略微提升吞吐量减少系统调用次数但代价是在连接洪峰到来时所有worker进程会争抢accept锁反而增加内核竞争。除非你确认服务器负载长期稳定且极高否则保持默认off更稳妥。3.2http块隐藏在sendfile和tcp_nopush背后的零拷贝真相http块是Nginx配置的主体其中两个指令常被当成“性能开关”随意开启却不知其原理sendfile on; tcp_nopush on; tcp_nodelay on;sendfile on启用Linux内核的sendfile()系统调用。它允许数据在内核空间直接从磁盘文件描述符复制到socket描述符完全绕过用户空间避免了传统read()write()方式的4次内存拷贝磁盘→内核缓冲区→用户缓冲区→内核socket缓冲区→网卡。这是Nginx高效传输静态文件的基石。tcp_nopush on配合sendfile使用。它告诉内核“等数据凑够一个TCP报文段MSS大小或者等到sendfile传输完成再一次性推送到网络”。这减少了小包数量提升网络效率。但它只在sendfile启用时生效。tcp_nodelay on禁用Nagle算法。Nagle算法会将小数据包缓存直到收到前一个包的ACK或凑够MSS才发送以减少小包。但对于Web交互如HTTP头、AJAX响应延迟比带宽更重要所以要关掉它。关键矛盾点tcp_nopush和tcp_nodelay看似冲突一个要攒包一个要立刻发但Nginx的精妙之处在于tcp_nopush作用于sendfile传输的文件数据而tcp_nodelay作用于非sendfile的普通数据如动态生成的HTML、JSON。两者分工明确共同优化。3.3 日志格式别让log_format成为性能黑洞默认日志格式log_format combined $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent;这很清晰但有个隐患$http_referer和$http_user_agent是字符串Nginx需在每次请求时动态拼接且长度不可控。当遭遇恶意UA如超长字符串攻击或Referer为空时日志写入可能变慢甚至阻塞worker进程。生产环境推荐精简版log_format main $remote_addr [$time_local] $request_method $uri $status $body_bytes_sent $request_time $upstream_response_time;去掉$http_referer和$http_user_agent它们对实时监控价值有限且可由前端埋点或CDN日志补充增加$request_time整个请求处理耗时毫秒用于性能分析增加$upstream_response_time如果反向代理后端此项显示后端响应时间是定位慢请求的关键。实战技巧用logrotate管理日志但切记在/etc/logrotate.d/nginx中添加copytruncate选项。否则Nginx在日志轮转后若未执行nginx -s reopen会继续往已被重命名的旧文件写入导致磁盘空间无法释放。copytruncate能安全地清空原文件无需重启Nginx。理解这些配置背后的“为什么”你才能在面对具体业务需求时做出有依据的取舍。比如当你需要极致静态文件传输性能时sendfile on和tcp_nopush on就是必选项而当你主要提供API服务且后端延迟波动大时$upstream_response_time日志字段的价值就远超$http_user_agent。4. 从“能访问”到“可交付”一个真实网站的完整配置拆解现在我们搭建一个典型的、有实际业务意义的网站一个包含静态资源HTML/CSS/JS、动态API接口由Python Flask提供、以及后台管理入口需密码保护的轻量级企业官网。它不是Hello World而是模拟真实项目中常见的混合架构。我们将用一份配置文件实现全部功能并逐行解释其设计逻辑。4.1 项目结构约定让配置与文件系统形成映射首先定义清晰的目录结构这是配置可维护的前提/var/www/my-site/ ├── html/ # 静态HTML、CSS、JS │ ├── index.html │ └── assets/ ├── api/ # Python Flask应用监听127.0.0.1:5000 │ └── app.py └── admin/ # 后台管理目录需HTTP Basic Auth └── dashboard.html为什么这样分html/对应用户可见的前端api/是后端服务独立进程运行admin/是敏感路径需额外安全层。Nginx配置将严格按此结构路由避免路径混乱。4.2 主配置文件/etc/nginx/sites-available/my-site创建配置文件sudo nano /etc/nginx/sites-available/my-site内容如下关键行已标注# 1. 定义上游服务Upstream——解耦Nginx与后端 upstream flask_api { server 127.0.0.1:5000; # 可添加多个server实现负载均衡 # keepalive 32; # 保持长连接减少握手开销 } # 2. HTTP服务块监听80端口处理所有请求 server { listen 80; server_name my-site.local; # 3. 根路径优先匹配静态文件再fallback到API location / { root /var/www/my-site/html; index index.html; # 尝试找对应文件找不到则交给flask_api处理 try_files $uri $uri/ flask_api; } # 4. API路径所有以 /api/ 开头的请求代理到Flask location /api/ { proxy_pass http://flask_api/; # 重要修正Host头让Flask知道原始域名 proxy_set_header Host $host; 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; # 超时设置防止后端卡住Nginx proxy_connect_timeout 5; proxy_send_timeout 30; proxy_read_timeout 30; } # 5. 后台管理路径保护 认证 location /admin/ { alias /var/www/my-site/admin/; auth_basic Admin Area; auth_basic_user_file /etc/nginx/.htpasswd; } # 6. 静态资源缓存大幅提升前端性能 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, immutable; # 启用gzip压缩需在http块中开启gzip on gzip_vary on; } # 7. 404处理统一返回静态页而非Nginx默认页 error_page 404 /404.html; location /404.html { internal; root /var/www/my-site/html; } # 8. 内部重定向将所有非文件请求交给Flask处理SPA路由 location flask_api { proxy_pass http://flask_api; proxy_set_header Host $host; 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; } }4.3 配置逐行深度解析每一行都是一个决策点upstream flask_api这不是必须的但强烈推荐。它将后端地址抽象为一个名字便于后续扩展如加第二台Flask服务器或调试curl http://flask_api/health可直连测试。keepalive 32开启连接池避免每次请求都重建TCP连接对高频API至关重要。try_files $uri $uri/ flask_api这是Nginx处理“前端路由”如React Router的核心。它按顺序检查$uri是否存在如/about→/var/www/my-site/html/about$uri/是否存在如/blog/→/var/www/my-site/html/blog/index.html都不存在则内部重定向到flask_api由Flask接管。关键flask_api是命名location只用于内部跳转不会暴露给客户端。proxy_pass http://flask_api/vsproxy_pass http://flask_api注意末尾的/proxy_pass http://flask_api/;会去掉匹配的/api/前缀再转发。例如请求/api/users实际发给Flask的是/users。proxy_pass http://flask_api;会保留完整路径发给Flask的是/api/users。大多数后端框架包括Flask期望前者所以务必加/。auth_basic和auth_basic_user_file这是最简单的HTTP Basic认证。生成密码文件sudo apt install apache2-utils sudo htpasswd -c /etc/nginx/.htpasswd admin # 输入密码生成加密后的凭据安全提醒Basic Auth的密码是Base64编码非加密必须配合HTTPS使用否则明文传输。生产环境建议用更安全的方案如OAuth2、JWT。expires 1y和Cache-Control public, immutable1y1年是静态资源强缓存的黄金值。immutable是HTTP/1.1新标准告诉浏览器“这个文件永远不会变即使用户按F5也不要重新验证”。它解决了max-age31536000下用户强制刷新仍会发If-None-Match请求的问题。这份配置已经是一个可投入生产的网站骨架。它没有魔法每一行都是对真实业务需求的回应静态资源要快API要可靠后台要安全错误要友好。接下来我们让它真正“活”起来。5. 启动、验证与排错从配置生效到问题闭环配置写完只是开始真正的挑战在于如何确保它100%按预期工作如何快速定位并修复那些“理论上应该没问题但就是不行”的问题这一节我分享一套经过上百个项目验证的标准化启动与排错流程它不依赖高级工具只用Linux自带命令却能覆盖95%的常见故障。5.1 四步启动法让Nginx从“配置正确”走向“服务可用”Step 1语法检查Syntax Checksudo nginx -t # 输出nginx: the configuration file /etc/nginx/nginx.conf syntax is ok # nginx: configuration file /etc/nginx/nginx.conf test is successful这是第一道防线。但注意nginx -t只检查语法和文件路径不验证upstream服务是否可达、不验证SSL证书是否有效、不验证日志路径是否有写入权限。它只是说“配置文件能被Nginx读取”。Step 2配置重载Graceful Reloadsudo nginx -s reload # 或更安全的sudo systemctl reload nginxreload会启动新worker进程待旧进程处理完现有连接后自动退出零停机。永远不要用restart先stop再start那会造成短暂服务中断。Step 3进程与端口验证# 检查Nginx主进程是否运行 ps aux | grep nginx | grep master # 检查worker进程数量应等于worker_processes设置 ps aux | grep nginx | grep worker | wc -l # 检查80端口是否被Nginx监听 sudo ss -tlnp | grep :80 # 输出应包含LISTEN 0 65535 *:80 *:* users:((nginx,pid1234,fd6))如果ss命令未找到监听说明Nginx根本没起来回到Step 1检查。Step 4基础连通性测试# 本地curl测试绕过DNS直连localhost curl -I http://localhost # 应返回HTTP/1.1 200 OK # 检查是否返回了正确的index.html内容 curl http://localhost | head -n 5 # 应看到HTML开头几行 # 测试API代理是否通 curl http://localhost/api/health # 应返回Flask应用的健康检查响应关键原则每一步验证一个单一维度。语法→进程→端口→连通性。如果某步失败就停在这一步深挖绝不跳到下一步。这是避免“问题叠加”导致排查迷路的核心。5.2 日志分析读懂Nginx的“求救信号”当网站无法访问时90%的线索藏在两份日志里/var/log/nginx/error.log记录Nginx自身错误配置错误、权限不足、上游连接失败/var/log/nginx/access.log记录每个请求的详细信息IP、URL、状态码、耗时。典型错误模式与解决方案error.log 错误片段可能原因解决方案open() /var/www/my-site/html/index.html failed (13: Permission denied)文件系统权限不足sudo chown -R www-data:www-data /var/www/my-siteconnect() failed (111: Connection refused) while connecting to upstreamupstream服务如Flask未运行或端口错误sudo systemctl status my-flask-app检查netstat -tlnp | grep 5000could not build the server_names_hash, you should increase server_names_hash_bucket_sizeserver_name过长或过多在http块中添加server_names_hash_bucket_size 128;client intended to send too large body客户端上传文件过大在http或server块中添加client_max_body_size 100M;实战技巧用tail -f实时追踪日志同时在另一个终端发起测试请求观察日志即时输出能极大缩短定位时间。例如# 终端1实时看错误日志 sudo tail -f /var/log/nginx/error.log # 终端2发起一个触发错误的请求 curl -X POST http://localhost/api/upload --data-binary large-file.zip5.3 一个真实排错案例HTTPS跳转死循环的完整溯源现象用户访问http://my-site.local浏览器报错ERR_TOO_MANY_REDIRECTS。排查链路确认问题存在curl -I http://my-site.local观察Location头是否在http和https间来回跳。检查Nginx配置找到server块中关于80端口的return 301 https://$host$request_uri;逻辑正确。检查上游服务curl -I http://127.0.0.1:5000发现Flask应用内部也做了if not request.is_secure: redirect(...)这是双重跳转的根源。验证X-Forwarded-Proto在Flask中打印request.headers.get(X-Forwarded-Proto)发现为http说明Nginx的proxy_set_header X-Forwarded-Proto $scheme;未生效。根因定位检查Nginx配置发现proxy_set_header指令被错误地写在了location /api/块内而location /块中没有该指令。当用户访问根路径时Nginx未传递X-Forwarded-ProtoFlask误判为非HTTPS。修复将proxy_set_header X-Forwarded-Proto $scheme;移到server块顶层或在location /块中也添加。这个案例说明Nginx排错不是“猜”而是建立一条从客户端请求经Nginx解析、转发、响应再到上游服务处理的完整数据流并在每个节点验证关键头信息和状态码。日志是证据配置是蓝图而curl和ss是你的探针。6. 进阶加固让网站从“能用”走向“可信”当网站能稳定运行后下一步是让它符合现代Web的安全与性能基准。这不是锦上添花而是规避风险的必要动作。以下三项加固措施实施成本低但收益巨大且每项都有明确的合规依据如OWASP Top 10、Google Lighthouse评分标准。6.1 HTTPS强制化不止是加证书更是信任链构建仅配置listen 443 ssl还不够。一个完整的HTTPS站点需满足证书有效性使用Lets Encrypt免费证书配合certbot自动续期协议与加密套件禁用不安全的SSLv2/v3、TLS 1.0/1.1只启用TLS 1.2HSTS头告诉浏览器“未来一年内只允许用HTTPS访问此域名”防止SSL剥离攻击。在server块中添加# 启用HTTPS监听 listen 443 ssl http2; # http2提升性能 ssl_certificate /etc/letsencrypt/live/my-site.local/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/my-site.local/privkey.pem; # 安全协议与加密套件Mozilla推荐的Intermediate配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # HSTS强制浏览器只用HTTPS持续1年 add_header Strict-Transport-Security max-age31536000; includeSubDomains; preload always; # OCSP Stapling加速证书状态验证 ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 1.0.0.1 valid300s; resolver_timeout 5s;注意preload表示你愿意将域名提交到浏览器HSTS预加载列表一旦加入用户首次访问也会强制HTTPS。提交前务必确保所有子域名都已支持HTTPS否则会导致子域名无法访问。6.2 安全头加固用HTTP头筑起第一道防线现代浏览器支持一系列安全响应头Nginx可轻松注入# 防止MIME类型嗅探攻击 add_header X-Content-Type-Options nosniff always; # 防止点击劫持Clickjacking add_header X-Frame-Options DENY always; # 内容安全策略CSP定义哪些资源可加载 # 此处为宽松策略生产环境需根据实际资源细化 add_header Content-Security-Policy default-src self; script-src self unsafe-inline unsafe-eval; style-src self unsafe-inline; img-src self data:; font-src self; connect-src self; frame-src none; always; # Referrer策略控制Referer头发送范围 add_header Referrer-Policy no-referrer-when-downgrade always;CSP内容安全策略是重中之重。unsafe-inline和unsafe-eval虽方便开发但存在XSS风险。生产环境应移除它们改用nonce或hash方式加载内联脚本。6.3 性能优化Lighthouse 90分的关键配置Google Lighthouse评分中性能Performance占比最高。Nginx可直接影响以下指标First Contentful Paint (FCP)通过gzip和brotli压缩HTML/JS/CSSTime to Interactive (TTI)通过http2减少连接数加快资源并行加载Total Blocking Time (TBT)通过proxy_buffering off对API和sendfile on对静态文件降低延迟。在http块中启用# 启用gzip压缩需安装nginx-extras gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; # 更优的Brotli压缩需编译安装brotli模块 # brotli on; # brotli_comp_level 6; # brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; # 启用HTTP/2需HTTPS http2 on;实测数据对一个1.2MB的HTMLJS包启用gzip后体积降至320KBFCP