🐛 问题表现
浏览器错误:
javascript
GET http://xx.xxx.xxx.xx/keyboard/keyboard-management.ef48a688dd95df4ddd57.js 404
Uncaught SyntaxError: Unexpected token '<'
🔍 问题排查过程
问题 1: 微应用 JS 文件 404
症状:
- 主应用正常加载
- 点击微应用菜单,JS 文件找不到
- 错误日志显示在
/data/apps/frontend/main/keyboard/下找文件
根本原因:
nginx
# ❌ 错误配置
location ~* .(js|css|png|...)$ {
root /data/apps/frontend/main; # 所有静态资源都去主应用目录找
}
location /keyboard/ {
alias /data/apps/frontend/keyboard/; # 这个规则永远不会生效
}
Nginx Location 匹配优先级:
- 正则匹配
~*优先级 > 普通前缀匹配 - 请求
/keyboard/xxx.js被正则规则拦截 - 使用
root /data/apps/frontend/main→ 404
解决方法:
nginx
# ✅ 使用 ^~ 提高优先级
location ^~ /keyboard/ {
alias /data/apps/frontend/keyboard/;
}
问题 2: JS 文件返回 HTML 内容
症状:
bash
GET http://xx.xxx.xxx.xx/keyboard/keyboard-management.js 200 OK
Uncaught SyntaxError: Unexpected token '<' # JS 文件内容是 HTML
根本原因:
nginx
# ❌ 错误配置
location ^~ /keyboard/ {
alias /data/apps/frontend/keyboard/;
try_files $uri $uri/ /keyboard/index.html; # 找不到文件就返回 HTML
}
请求流程:
- 请求:
/keyboard/xxx.js - 文件不存在(路径映射错误)
try_filesfallback 到index.html- 浏览器收到 HTML 内容,解析失败
问题 3: Nginx Alias 路径映射错误
症状:
bash
curl -I http://localhost/keyboard/keyboard-management.js
# 返回:301 Moved Permanently
# Location: http://localhost/keyboard/keyboard-management.js/
根本原因:
nginx
# ❌ Nginx 把 JS 文件当成目录处理
location ~ ^/keyboard/.*.(js|css)$ {
alias /data/apps/frontend/keyboard/; # 正则匹配 + alias 无法正确替换路径
}
Nginx Alias 指令问题:
alias指令会完全替换 location 匹配的路径- 在正则匹配中使用
alias容易出现路径映射错误 - Nginx 无法正确处理尾部斜杠,导致 301 重定向
✅ 最终解决方案
方案对比
表格
| 方案 | 配置方式 | 优点 | 缺点 |
|---|---|---|---|
| 方案 1 | 调整目录结构 + root | 配置清晰,路径匹配准确 | 需要修改目录结构 |
| 方案 2 | 精确的 alias 配置 | 不改变目录 | 配置复杂,容易出错 |
| 方案 3 | 简化配置 + 去掉 fallback | 最简单,最稳定 | 无 SPA fallback(但微应用不需要) |
最终采用方案 3(最简配置)
nginx
server {
listen 80 default_server;
server_name _;
# ✅ Keyboard 微应用(使用 ^~ 提高优先级)
location /keyboard/ {
alias /data/apps/frontend/keyboard/;
# ✅ 不使用 try_files,直接返回文件
add_header Access-Control-Allow-Origin * always;
}
# ✅ Mouse 微应用
location /mouse/ {
alias /data/apps/frontend/mouse/;
add_header Access-Control-Allow-Origin * always;
}
# API 代理
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
# ✅ 主应用(最低优先级)
location / {
root /data/apps/frontend/main;
try_files $uri $uri/ /index.html; # 只有主应用需要 SPA fallback
}
}
📚 关键知识点
1. Nginx Location 匹配优先级
nginx
# 优先级从高到低:
location = /exact/path # 1️⃣ 精确匹配
location ^~ /prefix/ # 2️⃣ 前缀匹配(不检查正则)
location ~ /regex/ # 3️⃣ 正则匹配(区分大小写)
location ~* /regex/ # 4️⃣ 正则匹配(不区分大小写)
location /prefix/ # 5️⃣ 普通前缀匹配
2. Root vs Alias
nginx
# root:拼接路径
location /static/ {
root /data/www;
# /static/file.js → /data/www/static/file.js
}
# alias:替换路径
location /static/ {
alias /data/files/;
# /static/file.js → /data/files/file.js
}
⚠️ Alias 注意事项:
- location 和 alias 的尾部斜杠必须一致
- 正则匹配 + alias 容易出问题
- 尽量避免在复杂场景使用 alias
3. Try_files 指令
nginx
# 语法
try_files $uri $uri/ /fallback.html;
# 工作流程
# 1. 尝试访问 $uri(文件)
# 2. 尝试访问 $uri/(目录)
# 3. 返回 /fallback.html
⚠️ 微应用注意:
- 微应用的静态资源(JS/CSS/图片)不应该 fallback 到 HTML
- 只有 HTML 页面路由需要 fallback
- 否则会出现"请求 JS 返回 HTML"的问题
🎯 Qiankun 微应用 Nginx 配置最佳实践
✅ 推荐配置模板
nginx
server {
listen 80;
server_name your-domain.com;
# 1️⃣ 微应用路由(使用 ^~ 提高优先级)
location ^~ /micro-app1/ {
alias /path/to/micro-app1/;
index index.html;
# 不使用 try_files,让 Nginx 直接返回文件或 404
add_header Access-Control-Allow-Origin * always;
}
location ^~ /micro-app2/ {
alias /path/to/micro-app2/;
index index.html;
add_header Access-Control-Allow-Origin * always;
}
# 2️⃣ API 代理
location ^~ /api/ {
proxy_pass http://backend:8080/;
}
# 3️⃣ 主应用(最低优先级,使用 SPA fallback)
location / {
root /path/to/main-app;
try_files $uri $uri/ /index.html;
add_header Access-Control-Allow-Origin * always;
}
}
✅ 关键要点
-
微应用路由必须使用
^~- 确保优先级高于其他规则
- 避免被正则规则拦截
-
微应用不使用
try_files- 静态资源直接返回,不 fallback
- 避免返回 HTML 导致 JS 解析错误
-
CORS 头必须设置
- qiankun 需要跨域加载微应用资源
add_header Access-Control-Allow-Origin * always;
-
路由顺序很重要
- 微应用路由放在前面
- 主应用路由放在最后
- API 代理放中间
-
目录结构建议
bash /data/apps/frontend/ ├── main/ # 主应用 ├── keyboard/ # 微应用 1 └── mouse/ # 微应用 2
🔧 调试技巧
1. 检查 Nginx 路由匹配
bash
# 查看访问日志
tail -f /var/log/nginx/access.log
# 查看错误日志
tail -f /var/log/nginx/error.log
# 测试文件是否存在
curl -I http://localhost/keyboard/xxx.js
# 查看返回内容
curl http://localhost/keyboard/xxx.js | head -c 100
2. 验证路径映射
bash
# 检查实际文件
ls -la /data/apps/frontend/keyboard/
# 测试 Nginx 配置
nginx -t
# 重新加载配置
systemctl reload nginx
3. 浏览器调试
javascript
// F12 → Network 面板
// 查看请求的 Response Headers:
// Content-Type: application/javascript ✅ 正确
// Content-Type: text/html ❌ 错误
📊 总结
表格
| 问题阶段 | 原因 | 解决方法 |
|---|---|---|
| 404 错误 | Location 匹配优先级错误 | 使用 ^~ 提高微应用路由优先级 |
| 返回 HTML | try_files 错误 fallback | 移除微应用的 try_files 指令 |
| 301 重定向 | Alias + 正则匹配路径错误 | 简化配置,避免复杂的正则匹配 |
核心原则:
- 微应用路由配置要简单直接
- 优先级要高于其他规则
- 静态资源要直接返回,不做 fallback
🎉 问题解决!