需求背景
今天处理了一个需求,需要将一个外部页面嵌入到我们自己的页面中,通过现有的微前端架构实现。
问题描述
外部页面的资源是以相对路径的形式引用的,例如使用 "publicPath: '.'"。在微前端架构下,通常的 Nginx 反向代理配置如下:
location ~* /subSystem {
proxy_pass http://subSystem:30970; # 注意最后没有 /
}
这种配置要求子应用的资源必须放置在 /usr/share/nginx/html/subSystem 目录下,即子应用的资源路径(publicPath)必须为 /subSystem/。对于内部子系统,我们可以要求其遵循这一规则,但对于外部页面则无法做到这一点。
解决方案
为了适应外部页面的需求,我们需要调整 Nginx 的反向代理配置,以便支持任意的资源路径。具体的配置如下:
location ~* /subSystem/(.*)$ {
proxy_pass http://ip:port/$1?$args;
}
其中,$1 是捕获的路径部分,$args 是查询字符串参数。
规则总结
- 路径重写: 如果
proxy_pass后面指定了路径名称,则会覆盖location中的路径,而不是简单拼接。 - 查询参数: 必须显式添加
$args以传递查询参数,否则它们将被忽略。
进一步的问题
在解决了上述问题后,又遇到了一个新的挑战:用户的 token 作为外部页面的查询参数没有生效,http://ip:port?token=xxx。尽管 token 值是正确的,但仍然不起作用。排查后发现,如果子应用使用的是前端路由的 hash 模式,那么需要以 http://ip:port/#/?token=xxx 的形式访问页面,这样路由系统才能解析成功。
注意事项
- 正常情况下,无需在 Nginx 层面对 hash 进行特殊处理,因为它默认会忽略 hash 值。
- 确保前端框架能够正确解析 hash 模式的路由。
URLSearchParams 小贴士
在使用 URLSearchParams 处理查询参数时,需要注意空格会被转换为 +。可以复制下面代码试一试:
const searchParams = new URLSearchParams();
searchParams.append('token', 'Bearer 1234');
searchParams.toString() // 'token=Bearer+1234'
解决方法
- 使用
%20替换空格:
javascript
const searchParams = new URLSearchParams();
searchParams.append('token', 'Bearer%201234');
console.log(searchParams.toString()); // 'token=Bearer%201234'
- 手动编码:
javascript
const searchParams = new URLSearchParams();
searchParams.append('token', encodeURIComponent('Bearer 1234'));
console.log(searchParams.toString()); // 'token=Bearer%201234'
这样,你可以根据具体需求选择合适的方法来处理查询参数中的空格。