如何正确配置Nginx以适配Vanilla JS单页应用(SPA)?
解决Vanilla JS单页应用的Nginx静态资源加载问题
我用Vanilla JS开发单页应用(SPA),需求是让Nginx无论用户输入什么URI都返回index.html。当前配置能实现路由跳转,但当访问/game、/chat这类非根路径时,浏览器加载图片、CSS、JS等静态资源会失败,求正确解决方法。
现有配置文件
nginx.conf
include mime.types; server { listen 8080; root /app; location / { try_files $uri /index.html; } } events {}
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Transcendence</title> </head> <body> <nav class="nav"> <a href="/" class="nav_link" data-link>Profile</a> <a href="/game" class="nav_link" data-link>Game</a> <a href="/chat" class="nav_link" data-link>Chat</a> </nav> <script defer type="module" src="src/js/index.js"></script> </body> </html>
Dockerfile
FROM nginx:1.24-bullseye COPY nginx.conf /etc/nginx/nginx.conf WORKDIR /app COPY index.html . COPY ./src ./src
目录结构
. ├── src │ ├── js │ │ └── index.js │ ├── css │ │ └── style.css │ └── assets │ └── logo.png ├── index.html ├── nginx.conf └── Dockerfile
解决步骤
1. 修复静态资源路径引用
问题根源:index.html里的静态资源用了相对路径(比如src="src/js/index.js"),当浏览器处于/game路径下时,会错误地请求/game/src/js/index.js,而这个路径不存在。
解决方法:把所有静态资源的引用改成绝对路径(路径开头加/):
修改后的index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Transcendence</title> <!-- CSS资源也需改成绝对路径 --> <link rel="stylesheet" href="/src/css/style.css"> </head> <body> <nav class="nav"> <a href="/" class="nav_link" data-link>Profile</a> <a href="/game" class="nav_link" data-link>Game</a> <a href="/chat" class="nav_link" data-link>Chat</a> </nav> <!-- JS资源改为绝对路径 --> <script defer type="module" src="/src/js/index.js"></script> </body> </html>
2. 优化Nginx配置(可选但推荐)
现有配置已经能处理SPA路由,但可以拆分静态资源和路由请求的处理逻辑,提升性能并避免不必要的跳转:
修改后的nginx.conf:
include mime.types; server { listen 8080; root /app; # 优先处理静态资源,添加缓存优化 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; } # 所有非静态资源请求返回index.html,处理SPA路由 location / { try_files $uri $uri/ /index.html; } } events {}
配置说明:
- 第一个
location块匹配常见的静态资源后缀,直接返回对应文件,同时设置长期缓存,减少重复请求。 - 第二个
location块处理所有其他请求,返回index.html,确保SPA的前端路由正常工作。
验证方法
- 完成上述文件修改后,重新构建Docker镜像:
docker build -t my-spa .
- 运行容器:
docker run -p 8080:8080 my-spa
- 访问
http://localhost:8080/game或其他非根路径,静态资源应能正常加载,SPA路由也能正常跳转。
内容的提问来源于stack exchange,提问作者Eugene Grigorian
相关产品推荐
相关产品推荐

