部署场景:Nginx统一托管
场景:子应用不独立起服务,全部挂在同一个 nginx 下
很多公司不想给每个子应用单独起一个 node/nginx 服务。更省事的做法是:主应用和所有子应用的构建产物都是纯静态文件,统一放在一台 nginx 的站点目录下,通过 URL 路径(前缀)区分,用 try_files 解决 history 路由刷新 404。
目录结构
服务器上按"一个应用一个目录"放静态产物:
/var/www/
├── main/ # 主应用构建产物
│ └── index.html
├── sub-vue/ # 子应用 vue 构建产物
│ └── index.html
└── sub-react/ # 子应用 react 构建产物
└── index.html
nginx 配置
server {
listen 80;
server_name your.domain.com;
# 主应用(根路径)
root /var/www/main;
index index.html;
# 子应用 vue,挂在 /vue 前缀下
location /vue/ {
alias /var/www/sub-vue/;
try_files $uri $uri/ /vue/index.html;
}
# 子应用 react,挂在 /react 前缀下
location /react/ {
alias /var/www/sub-react/;
try_files $uri $uri/ /react/index.html;
}
# 主应用 history 路由兜底(放最后)
location / {
try_files $uri $uri/ /index.html;
}
}
try_files $uri $uri/ /vue/index.html 是核心:用户刷新 /vue/orders 时,nginx 先找真实文件(找不到)→ 找目录(也找不到)→ 回退到 /vue/index.html,由子应用前端路由接管渲染。
配套要改的三处配置(容易漏)
1. 子应用路由 base = 挂在主应用的路径前缀
// 子应用 vue 的 router(vue-router)
base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
不设 base,刷新 /vue/orders 时子应用路由会认为自己在 /orders,页面空白或 404。
2. 子应用构建 publicPath = 路径前缀
资源(JS/CSS)必须按前缀产出,否则在 /vue 页面里引用的 /static/js/xxx.js 会 404:
// vue.config.js 或 webpack output
publicPath: process.env.NODE_ENV === 'production' ? '/vue/' : '/',
3. 主应用 entry 指向静态路径
registerMicroApps([
{
name: 'sub-vue',
entry: '/vue/index.html', // 或 '/vue/',同源相对路径即可
container: '#subapp-viewport',
activeRule: '/vue',
},
]);
常见问题
| 问题 | 原因 | 解法 |
|---|---|---|
| 子应用页面刷新 404 | 子应用没配 base,或 nginx 没回退 | 路由 base='/vue' + try_files ... /vue/index.html |
| 子应用 JS/CSS 404 | publicPath 没带前缀 | 构建设 publicPath='/vue/' |
| 子应用里图片/字体 404 | 资源相对路径 | 同样走 publicPath;或子应用统一用绝对前缀路径 |
alias 下 try_files 回退不对 | alias 的回退 URI 规则易踩坑 | 回退路径带完整前缀(/vue/index.html);仍不行就改用 root + 调整目录 |
| 主应用刷新 404 | 主应用自己没兜底 | 主应用 location / { try_files ... /index.html } |
提示:这里的"挂同一台 nginx"既可以是同一台机器,也可以是同一个 CDN / 对象存储——只要主应用和子应用在同源下通过前缀区分,
entry就能用相对路径,也不用处理跨域。子应用之间各自独立构建、独立上传,发版互不影响。