最近遇到一个需要合并两个域名到一个域名下的需求,记录一下解决过程。
起源
一个项目需要和其他公司协作完成,遇到这么一个问题:页面要在对方微信中使用,并且要使用微信JS-SDK做一些操作。但微信公众平台可以配置的JS接口安全域名只有三个,而对方公司留给我们的名额只有一个,这就要求我们必须把两个域名合并成一个来提供服务。
需要合并的两个域名:
wxpage.xingshulin.com、utm.xingshulin.com
需要合并到的域名:
open.xingshulin.com
合并之后由一个域名下的两个一级目录分别提供服务:
open.xingshulin.com/wxpage、open.xingshulin.com/utm
解决思路
配置Nginx
做之前就想起之前遇到过一次类似的需求,是把 blog.xingshulin.com
合并到了 www.xingshulin.com/blog
下,是运维帮忙配置的Nginx,参考当时的配置自己配了一下:
1 | upstream com_qa-weather { |
上次只简单配置了 location 的 proxy_pass(location 和proxy_pass的绝对路径相对路径也是要注意的一个点,具体请看这里),也就是访问 nginx.leotian.cn 时对 localhost:8080 做反向代理,透明传输,这样配置的话,我们看下访问 nginx.leotian.cn/weather/ 请求到的是什么:
可以看到,服务的根页面正常返回,但是根页面上请求的资源文件都是 404,因为资源文件并没有被反向代理,而我们域名的根目录下也没有 static/xx
这些资源文件,自然就404了,如果要解决这个问题,我们需要把 weather 服务的所有资源文件都放在 /weather/ 下,上次把 www.xingshulin.com/blog
代理到 blog.xingshulin.com
服务时就是这么做的,把 blog 服务的所有的资源文件都放在了一级目录 /blog 下:
那么如何不挪动资源文件的进行修改呢?我们增加一个 location 配置:
1 | location / { |
我们看一下上面这段配置的逻辑(上面用到了 rewrite 模块的一些功能,具体使用请参考文档和文章):
如果请求的 referer 包含 weather,我们就能知道这个请求应该是指向 weather 服务的,那么 rewrite URL 为 /weather/原请求地址
,然后再经过第一个 location 进行反向代理,页面请求的资源文件就也可以拿到了,就不用再要求服务去把页面请求的资源文件挪动到 /weather 目录下了。配置好后我们实验一下:
恩,页面终于正常打开了。但对 wxpage 做相同的配置:即 open.xingshulin.com/wxpage 代理到 wxpage.xingshulin.com 之后。我们再次请求,发现所有资源文件都返回200,内容也正常返回,但是页面并没有渲染出来:
这又是什么原因呢?思考之后,我们想到应该是前端路由的问题,因为服务已经返回了全部的资源,除了ajax请求,和后端的交互应该到此为止了。接下来我们看一下前端路由出了什么问题。
路由配置
如果是后端路由,那么以上的配置应该是没有问题的,以上两个 location 已经保证我们所有请求都可以正确导向:
访问 open.xingshulin.com/wxpage/xxx 页面,请求打到 wxpage.xingshulin.com/xxx
页面上的资源请求,根据 referer 判断应该去哪个服务请求,从而代理到正确的资源地址
但这次要配置的两个服务都是SPA,前端路由,也就是说到了前端才判断路由或者说路由交给了前端,服务返回页面和资源文件后就不再处理路由的问题了,而增加一级目录后,访问的路径变成了:/wxpage/az,旧的前端路由列表只有 /az
,并没有 /wxpage/az
,所以出现了无法匹配的问题(如果前端路由写了404,就跳到404了)。
所以即使不挪动资源文件,但是写了前端路由的话,也是要对路由进行一定的修改,我们的项目目前的路由使用 vue-route 的 History 模式,配置如下(部分):
1 | const routes = [{ |
现在我们在前端进行重定向,做如下修改:
1 | const wxpageRoutes = routes.map(route => ({ |
上面配置的效果就是改成了:
1 | const routes = [{ |
也就是说访问:/az/xxx
重定向到 /wxpage/az/xxx
,这样配置之后,可以兼容之前发出去的链接,结合前面的Nginx配置,我们就实现了使用一级目录对一个域名的代理。
但是配好后刷新时候还是有点问题,其实刷新问题是 history 模式固有的问题(可以看这里了解更多)。这次我们修改路由后,也要对
总结
这次配置涉及到了对Nginx和前端路由的配置,两个配合最终实现了我们一开始的需求:合并两个域名到一个域名的一级目录下。配置过程中在调试Nginx时发现了echo模块,是在nginx程序上扩展了echo输出字符的功能,对于调试很方便。如果觉得安装模块很麻烦,再分享一个调试Nginx配置的小技巧。
如果只是前端同学可能看起来有点困难,但还是建议掌握一下反向代理这个技能,毕竟现在都讲全栈开发,即便是纯前端,不懂http也只能做切图仔了。