Nginx + Next.js静态文件上的404



我有一个带有nginx服务器的WordPress站点(在/var/www/html/路径中),现在我希望一个特定的页面通过代理在nextjs(/var/www/html/路径中)中,用于端口3000。 我正在请求,example.com/specific-next-page页面确实加载了,但找不到所有静态文件 (js/css) (404)。例如:

GET https://example.com/_next/static/css/1ca183f3cca214b7.css net::ERR_ABORTED 404

这是我在nginx日志中看到的。2022/06/10 14:47:25 [error] 3015605#3015605: *10 open() "/var/www/html/_next/static/BA1dIGPMYI7hn430ayZ2f/_buildManifest.js" failed (2: No such file or directory), client: 172.70.200.XXX, server: example.com, request: "GET /_next/static/BA1dIGPMYI7hn430ayZ2f/_buildManifest.js HTTP/2.0", host: "example.com", referrer: "https://example.com/specific-next-page"

我知道问题是nginx正在/var/www/html文件夹中查找文件,该文件夹是WordPress文件夹,而nextjs在/var/www/next也就是说,静态文件的正确路径是/var/www/next/.next/static

我真的尝试了很多选择,但我失败了。 这是我的nginx配置文件。

upstream php-handler-https {
server 127.0.0.1:9000;
}
server {
listen 443 ssl http2 ;
listen [::]:443 ssl ;
server_name example.com www.example.com; 
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
root /var/www/html/;
index index.php;
client_max_body_size 2G;
fastcgi_buffers 64 4K;
access_log /var/log/nginx/wordpress_https_access.log combined;
error_log /var/log/nginx/wordpress_https_error.log;
server_tokens off;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# NEXT PROXY
location /__nextjs_original-stack-frame {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /content {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
location /_next {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}

# specific-page - next.js
location /specific-next-page {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
# END NEXT

location / {
try_files $uri $uri/ /index.php?$args ;
}
# protected area (XHProf)
location ^~ /xhprof/xhprof_html/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/xhprof;
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_FLAG "session.auto_start=off n mbstring.encoding_translation=off";
fastcgi_param PHP_VALUE "assert.active=0 n mbstring.http_input=pass n mbstring.http_output=pass";
fastcgi_pass php-handler-http ;
fastcgi_read_timeout 60s;
}
}
# protected area (phpmyadmin)
location ^~ /mysqladmin/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/phpmyadmin;
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_FLAG "session.auto_start=off n mbstring.encoding_translation=off";
fastcgi_param PHP_VALUE "assert.active=0 n mbstring.http_input=pass n mbstring.http_output=pass";
fastcgi_pass php-handler-http ;
fastcgi_read_timeout 60s;
}
}
location ^~ /wp-admin/install.php {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/wpadmin;
location ~* .(htaccess|htpasswd) {
deny all;
}
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/html/xhprof/external/header.php";
fastcgi_pass php-handler-https;
fastcgi_read_timeout 60s;
}
}
location ~* .(htaccess|htpasswd) {
deny all;
}
location ~* .(?:ini|conf|txt)$ {
deny all;
}
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/html/xhprof/external/header.php";
fastcgi_pass php-handler-https;
fastcgi_read_timeout 60s;
}
# set long EXPIRES header on static assets
location ~* .(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
access_log off;
}
}

你明白nginx如何选择处理请求的位置吗?您是否了解根据使用的修饰符确定的位置优先级?您是否阅读location指令文档?您已在配置中使用了^~位置修饰符。你明白它是什么意思以及它是如何工作的吗?

由于您的正则表达式location ~* .(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ { ... }如果没有^~修饰符,任何前缀位置都不会处理对这些文件类型的任何请求(好吧,至少在最长的前缀中会有另一个正则表达式位置之前)。配置的最小修复至少是使用^~修饰符作为前缀位置/_next

location ^~ /_next {
...
}

但是,由nginx本身提供静态文件而不代理对应用程序的请求将更加有效。为此,您可以使用以下位置:

location ^~ /_next/static/ {
alias /var/www/next/.next/static/;
try_files $uri =404;
}

通常,使用任何可以避免的额外正则表达式位置都会降低性能,因为它(很可能,如果请求不会被之前具有修饰符或正则表达式位置的另一个前缀位置捕获^~)将消除昂贵的 PCRE 库调用来执行与正则表达式模式的匹配。这两个位置:

location ~* .(htaccess|htpasswd) {
deny all;
}
location ~* .(?:ini|conf|txt)$ {
deny all;
}

可以轻松组合成一个:

location ~* .(?:htaccess|htpasswd|ini|conf|txt)$ {
deny all;
}

如果禁用资产请求日志记录对您来说不是必需的,那么:

location ~* .(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
access_log off;
}

可以用更大但更有效的配置替换,以根据Content-TypeHTTP 响应标头添加缓存策略(根据 nginx 1.21 使用的默认 MIME 类型):

map $sent_http_content_type $expires {
image/jpeg                     30d;
image/gif                      30d;
image/x-ms-bmp                 30d
image/x-icon                   30d;
image/png                      30d;
text/css                       30d;
application/javascript         30d;
application/x-shockwave-flash  30d;
default                        off;
}
server {
...
location / {
try_files $uri $uri/ /index.php?$args;
expires $expires;
}
...
}

此外,如果需要,这样您就可以轻松地将相同的缓存策略添加到Next.js应用程序中(不再需要使用^~修饰符):

location /_next/static/ {
alias /var/www/next/.next/static/;
try_files $uri =404;
expires $expires;
}

我在这里更全面地描述了这种方法。


关于配置中的以下行:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

这些用于 WebSocket 协议代理,如果未使用 WebSocket,在某些情况下可能会破坏您的应用。我真的怀疑您需要为每个Next.js相关的位置提供这些线路。在此处阅读更多技术细节。

如果/var/www/html是 Web 服务器的根目录,则不会从/var/www/next向客户端提供文件。.next文件夹必须位于nginx提供的位置,并且对客户端公开可用。

我建议.next置于/var/www/html之下

最新更新