由Nacos允许配置访问代理启发的Node前端部署路径转发探究
本文相关代码地址
待补充
约定
SPA表示Sinlgle Page Application,单页面应用,使用vue、react等响应式前端框架开发的node应用。
前端开发启动端口为vite默认的5173
后端端口为8081
分离部署时前端端口为8001
转发部署时前端端口为8002
入题
Nacos为什么能够配置nacos-proxy转发实现转发访问?
在内网开发的时候,因为nacos端口没有开放,但我又需要访问nacos修改配置,于是就想能否使用一个已开放的端口来转发到nacos,实现正常访问和配置的需求。
Nginx配置片段:
server {listen 8080; # 监听8080端口server_name localhost;# 匹配路径为 /nacos-proxy 的请求(代理Nacos)location /nacos-proxy/ {# 转发到Nacos实际地址,注意结尾的 / 必须添加,否则路径会拼接错误proxy_pass http://127.0.0.1:8848/;# 传递必要的请求头,确保Nacos正常解析proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# 超时设置proxy_connect_timeout 5s;proxy_read_timeout 30s;proxy_send_timeout 30s;}}
效果就是,当我访问 localhost:8080/nacos-proxy/nacos时,我确实能够访问nacos了,而且界面、js、css加载也都没问题。我由此想到的是,这是如何做到的?我是否也可以做一个这样的前端应用?这样是不是就能实现一个端口,多个路径,访问多个前端应用的效果了(节省对外端口)?
下面就是由此而来的探究 了。
一个简单的前端项目
一个简单的vite+vue3项目(先不加路由参数,仅仅最简单路由方式,浏览器地址不变)
因为我之前就做了一个简易版的文件服务器,只有一个vue主页面文件,所以我就直接以这个工程作为基础了。
前端介绍
vite.config.js配置本地server和/api转发:
export default defineConfig({plugins: [vue()],base: './', server: {proxy: {// 配置axios请求的代理规则'/api': {target: 'http://localhost:8081/', // 后端服务器地址changeOrigin: true, // 允许跨域// rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径,去除前缀// secure: false, // 如果是https接口,需要配置这个参数// ws: true, // 如果要代理websockets},}}
})
这里的localhost:8081就是下面说到的后端。
两个简单的vue组件:
这是router/index.js路由配置,就最简单的一个示例:
{path: '/hello1',name: 'Hello1',component: () => import('../views/Hello1.vue')},{path: '/hello2',name: 'Hello2',component: () => import('../views/Hello2.vue')}
App.vue
<div><div><router-link to="/hello1">打开hello1</router-link><br/><router-link to="/hello2">打开hello2</router-link></div><hr/><router-view></router-view></div>
这个页面加了个后台的hello world通信。
axios封装:
import axios from 'axios'// 读取 .env 中定义的 API 前缀
const API_BASE_URL = '/api'// 创建 axios 实例
const request = axios.create({baseURL: API_BASE_URL,timeout: 10000
})export default request
Hello2.vue使用request:
function handleClick() {request.get('/hello').then(response => {console.log(response.data);result.value = response.data}).catch(error => {alert(error);});
}
后端介绍
springboot服务:
@RequestMapping("/hello")public String hello() {return "hello world from server!";}
这个项目反正是足够简单了。
启动前后端
前端开发启动,后端springboot服务
主页效果:
Hello2页面:
前后端一体化测试
不考虑路由
前端打包,后端整合前端后启动
前端执行npm run build打包
把前端dist目录下的内容复制到后端resources/static目录下:
后端不需要额外配置,使用spring约定的静态资源映射即可。
我的后端端口是8081.直接访问localhost:8081
点击hello1和hello2的链接,也确实能实现跳转,浏览器地址也发生了变化。
这里发现hello2的后台测试仍然可用,是因为我的后端Controller本身也是/api开头的。另外注意,vite.config.js里的proxy代理配置,不同于nginx的/斜线逻辑,它不会影响“路径拼接”逻辑,Vite 的 proxy 始终是“路径拼接”模式。
SPA配置借助ResourceHandler
如果不考虑路由直接浏览器访问的问题,上面的部署就算完成了,但是如果想直接访问某个url,就会发现有问题了。这里,我直接访问localhost:8081/hello2,结果就报错了:
这很好理解,因为没有名字为hello2的静态资源,回忆一下,如果前端部署到nginx上去,是不是我们需要配置一个try_files $uri $uri/ /index.html,这就是所谓的SPA单页面应用,其他的路由地址也应该指向index.html。在WebConfig.java里添加如下配置:
@Configuration // 标记为配置类
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 1. 显式配置静态资源路径(可选,Spring Boot 默认已配置)registry.addResourceHandler("/**").addResourceLocations("classpath:/static/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver() {@Overrideprotected Resource getResource(String resourcePath, Resource location) throws IOException {Resource r = super.getResource(resourcePath, location);if (r == null || !r.exists()) {return new ClassPathResource("/static/index.html");}return r;}});}}
这里没有太好的办法,没法直接配置viewController转发:
// 这个配置不行@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/**").setViewName("forward:/index.html");}
这个配置会出现一个问题,就是访问的时候,会被forward到/index.html,但是,/index.html也会匹配/**,出现无穷递归,500错误。
或许你会想配置addResourceHandler:
// 这个配置不行@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 1. 显式配置静态资源路径(可选,Spring Boot 默认已配置)registry.addResourceHandler("/**").addResourceLocations("classpath:/static/index.html");}
但很不幸,依然不好使,因为resourceLocations要求是目录,访问/hello2的时候,他实际找的是
/static/index.html/hello,但并没有这个文件。
SPA配置借助HandlerInterceptor
刚才那种方式可能不太好理解,也可以用HandlerInterceptor的方式拦截请求,然后手动转发:
@Configuration // 标记为配置类
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new HandlerInterceptor() {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String path = request.getRequestURI();// 若不是 /api 开头、且不是静态资源,且不是/index.html本身,转发到 index.htmlif (!path.startsWith("/api") && !isStaticResource(path) && !path.startsWith("/index.html")) {request.getRequestDispatcher("/index.html").forward(request, response);return false;}return true;}// 辅助方法:判断是否为静态资源(assets或图标等)private boolean isStaticResource(String path) {return path.startsWith("/assets/") || path.endsWith("favicon.svg");}});}}
这种可能更好理解一点,直接拦截请求,判断url是后端请求或静态资源或index.html本身则直接放行,否则直接forward到index.html上,实现nginx里的try_files语义。
SPA借助子目录
其实还有一种方法,就是借助子目录的方式。/hello2的路由跳转,问题就在于/**匹配的范围太大了,让他的范围缩小一下不就行了?比如我定义一个前缀,叫fileserver,然后配置/fileserver/**到classpath:/static/,然后访问localhost:8081/fileserver,下面就直接试一下:
我预想的是访问/myserver能打开/fileserver/index.html,然后静态资源自动从fileserver目录找,静态资源也放到fileserver子目录了,不出意外的又报错了:
访问: localhost:8081/myserver
发现问题是index.html里引入的js和css资源文件没有带fileserver前缀,这时候就需要考虑前端配置里的base了。(webpack中为publicPath)
修改前端路径前缀
base: '/fileserver',
修改前端路由路径名称
const router = createRouter({history: createWebHistory('/myserver'),routes
});
这一步是为了让访问的时候,路由router组件也认为应用是在/myserver下的,然后点击hello1、hello2跳转的时候,往/myserver上跳,进而被后端viewController拦截,去实际访问fileserver目录下的index.html。这样浏览器上的url显示会美观一些,一直是/myserver。当然了,这里可以是任何名字,比如打包的名字可以叫myserver,路由的名字叫fileserver,子目录也叫fileserver,访问的路径就是localhost:8081/fileserver。
前端启动测试
前端启动开发服务,访问: localhost:5173/fileserver,显示正常。但有个缺点是,/fileserver和/myserver两个路径有点杂糅了,不太美观。前者是为了让css、js等静态资源访问的时候不被viewController拦截,直接访问;后者是为了访问/myserver/index.html不被无限重定向,直接指向统一的/fileserver/index.html,也就是SPA。
打包
查看打包后的index.html文件,可以发现,js和css都带上了fileserver前缀了。
<script type="module" crossorigin src="/fileserver/assets/index-CBUZrX7x.js"></script>
<link rel="stylesheet" crossorigin href="/fileserver/assets/index-CMtyiuEH.css">
把新打包的资源放到springboot服务的fileserver子目录下。访问的时候,路径为:
http://localhost:8081/myserver/,能够正常访问,路径也没有乱。
直接访问地址 http://localhost:8081/myserver/hello2 也能正常访问。
HASH路由模式(Nacos为此模式)
其实还有一种方式,而且更简单,只不过他有个缺点是url会带一个#符号,可能不如url的方式美观,如果对url有明确要求的,这种方式可能并不适合。
前端修改:
export default defineConfig({plugins: [vue()],base: './', server: {...
这里修改的是,base属性,注意改为./相对路径,其实这里不改也可以,我是模拟了一下nacos的配置,如果不考虑配置nginx二次转发,可以保持为'/'.
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes
});
重点就是router/index.js里,把路由模式改为Hash模式了。
启动前端测试
注意到,访问的url变成了http://localhost:5173/#/hello2,这就是hash模式,他的#后面的部分,就是路由,对应router配置里的path部分。
打包
打包后,直接放到src/main/resources/static目录下。同时配置一下WebMvcConfig.java
这里配置了两个转发,其实配置第一个就可以,我这里是为了演示这种方式的使用有多么简单便捷,两个路径都能进行完整的访问使用。
可见,两个url都能访问,而且URL感觉很干净,也不需要操心index.html重定向的问题了。根本原因在于,路由的改变,并不会改变url本身,而是在url后面的#后面加了一些内容,因此我们只需要把/根路径映射到index.html文件即可。下面为豆包对#哈希片段的解释:
浏览器在发送 HTTP 请求时,会自动忽略 # 及其后面的内容,只将 # 前面的部分发送给服务器。
因此哈希的变化不会触发页面刷新或向服务器发起新请求
这使得前端可以在不重新加载页面的情况下,通过改变哈希值来管理路由状态
直接访问路径 http://localhost:8081/#/hello2 或 http://localhost:8081/fileserver#/hello2 也能正常打开页面。
前后端分离测试
上面测试了前后端一体化的方式,对于小型应用来说,前后端放一起是最优解,最简便。但对于稍大一些的项目来说,我们应该考虑前后端分离部署。前后端分离部署相对来说比较简单,后端不需要做额外配置,只需要保证/api对应的controller能访问即可,主要是前端和nginx的配置,下面分几种典型情况来讨论。
nginx前置知识
有的同学可能不知道如何在本地启动一个nginx,可以参考我的方法。
首先下载一个小皮,https://m.xp.cn/phpstudy,点击下载(注意下载的是windows版本)
安装后默认应该已经内置了nginx,如果没有,也可以在软件管理里面,进行安装:
然后就可以在首页里面,进行nginx的启动和停止了。
具体的配置文件位置,可以在设置里面,进行点击,将会自动打开nginx.conf文件。
也可以在phpStudy快捷方式上右键,打开所在位置,然后在extensions目录下找nginx那个目录,手动打开配置文件,手动执行nginx.exe命令。
推荐手动打开nginx.conf文件进行编辑,使用小皮的首页进行启停。
base为/的情况
这是最常见的情况,单个应用不带base,直接访问的情况。
前端的base配置为:
base: '/'
router/index.js配置为:
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes
});
也就是全部采用默认,执行npm run build打包。
在nginx安装目录下,建立一个fileserver目录:
把前端打包的静态资源放进去。然后修改nginx.conf配置:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location / {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11/fileserver;index index.html;try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
这里/api的配置需要注意一下,这是后端访问的反向代理。
访问截图:
直接刷新浏览器也没有任何异常。
base为./的情况
如果我想让访问的url变成/fileserver呢?
仅仅修改刚才的base配置:
base: './'
然后修改router/index.js配置为
const router = createRouter({history: createWebHistory('/fileserver'),routes
});
这里配置router前缀,是为了让浏览器展示好看,也是为了直接刷新时能走到try_files指令。
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ /fileserver/ {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11;index index.html;try_files $uri $uri/ /fileserver/index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
访问地址为:http://localhost:8001/fileserver/,访问正常,直接访问 http://localhost:8001/fileserver/hello2 也能正常显示。
关键在于将try_files改为/fileserver/index.html,因为/fileserver/hello2/index.html并不存在。
注意,这里将base设置为./是必要的,否则就会出现如下报错:
因为默认/是从根路径开始的,而不是当前路径,就会出现找不到的情况,而./就是为了自动拼接/fileserver前缀,从而在访问js css静态资源时也能通过location ^~ /fileserver找到资源。
如果不想让base为./,而是正常的fileserver,那就是下面要说到的情况了。
base为/fileserver的情况
base配置:
base: '/fileserver',
router/index.js配置:
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes
});
将打包资源放到nginx的fileserver子目录下。
nginx配置:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ /fileserver/ {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11;index index.html;try_files $uri $uri/ /fileserver/index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
与上面base为./没什么明显区别,效果一致。
base为/的HASH路由模式
base为/的时候:
base: './',然后router/index.js也是/的情况。
nginx使用配置:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ / {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11/fileserver;index index.html;try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
访问界面:
直接刷新也没有异常。
base为/fileserver的HASH路由模式
base: '/fileserver',然后router/index.js也是/fileserver的情况。
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ /fileserver {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11;index index.html;try_files $uri $uri/ /fileserver/index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
直接刷新也没有问题。
转发测试
一开始的目标就是想用一个端口,配置不同的url前缀来打开不同的web应用,节省对外暴露的端口数量,实现类似nacos-proxy那种的转发机制。不忘初心,现在我们终于走到了这一步了。
下面测试使用nginx配置上述应用的转发,也就是通过配置nginx的proxy_pass指令,实现一个http server端口,不同的url路径,打开不同的前端应用的目标。
转发测试考虑上述所有情况的nginx转发,我这里只考虑带prefix的url转发的情况,不考虑直接/跟根路径转发的情况。
一体版借助ResourceHandler或HandlerInterceptor
ResourceHandler和HandlerInterceptor这两种情况可以认为是一样的,只不过借助的springmvc的机制不同,前者是静态资源处理,后者是dispatcherServlet拦截器,目标都是实现静态资源的重定向。
base: '/',
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes
});
后端相关代码就不贴了,跟前文一样。最后直接访问地址 http://localhost:8081/hello2 能正常访问,直接刷新也没问题。
配置nginx:
server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8081/;}}
结果在访问的时候,出现index.html里的css和js访问失败,因为路径是http://localhost:8002/assets/index-CW2zdT2a.js,这里没有带 /fileserver前缀。修改前端base为./,重新打包。
这次js文件的访问路径就变成 http://localhost:8002/fileserver/assets/index-gNdbgAzY.js 了。
但直接刷新浏览器,仍然不行,可以再次修改,router/index.js里的配置:
const router = createRouter({history: createWebHistory('/fileserver'),routes
});
前端重新打包,这样就能实现转发后刷新也没问题,但这样的缺点就是,他也影响了原来一体版的访问体验。如果就是为了转发,那就这么配即可。
如果这时点击后台通信测试按钮,会发现不通,需要把/api同时代理,增加nginx配置:
location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}
当有多个应用时,建议后台的controller路径也有一定的规范,比如/fileserver-api。
仅仅想做到转发可用,而不关心浏览器直接刷新时报错的问题,那么把base改为./就已经做到了。
一体版借助子目录
前后端的修改参考前文。直接访问的路径为:
http://localhost:8081/myserver/,nginx转发配置为:
server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /myserver/ {proxy_pass http://localhost:8081;}location /fileserver/ {proxy_pass http://localhost:8081;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
注意这里要同时配置/myserver和/fileserver的转发,前者是为了打开SPA单页,后者是为了静态资源加载。访问结果正常,直接刷新浏览器也没有问题(因为路由带了/myserver前缀)。
一体版HASH路由模式
前后端配置参考前文,base为./,router/index.js为/。nginx配置为:
server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8081/;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
访问没问题,刷新浏览器有问题,因为url变成 http://localhost:8002/hello2 了,下文带prefix的能解决此问题。
一体版HASH路由模式带prefix
修改base为/fileserver,router/index.js为/fileserver,重新打包。
nginx配置不变,这次就完全正常了,附截图:
分离版base为/的情况
这种方式不可行,因为转发的prefix是/fileserver,但index.html加载的js css是/assets/xxx 是找不到的,不贴代码和截图了。
分离版base为./的情况
分离版就是将前端部署到nginx的情况。下面依次测试。
修改base为./,路由为/,打包,部署到nginx。前端nginx配置为:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ / {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11/fileserver;index index.html;try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
转发nginx配置为:
server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8001/;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
访问http://localhost:8002/fileserver/是可以正常访问的,不过访问hello2的时候,url显示为http://localhost:8002/hello2导致直接刷新会报错,解决办法是修改router/index.js为/fileserver,缺点是访问原服务也会带着/fileserver前缀。
修改后的前端nginx配置:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径# 这里没有写成^~ /是因为,否则刷新/fileserver/hello2会报找不到hello2,因为没有/index.htmllocation ^~ /fileserver {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11;index index.html;try_files $uri $uri/ /fileserver/index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
转发nginx配置:
server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8001/fileserver/;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
多少有点丑陋,所以还是用下面的base为/fileserver的方式较好。
分离版base为/fileserver的情况
此时base和router/index.js都是/fileserver,
nginx配置与上面修改后的前端nginx配置完全一致,就不贴了。
访问http://localhost:8001/fileserver和http://localhost:8002/fileserver都没问题,也能直接刷新。
分离版HASH路由模式
base为./,router/index.js为/
nginx配置为:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ / {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11/fileserver;index index.html;try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8001/;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
http://localhost:8001/和http://localhost:8002/fileserver都能访问,也都能刷新。
分离版HASH路由模式带prefix
base为/fileserver,router/index.js为/fileserver.
nginx配置为:
server {listen 8001;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /fileserver/ 路径location ^~ /fileserver {root D:/Programs/phpstudy_pro/Extensions/Nginx1.15.11;index index.html;try_files $uri $uri/ /fileserver/index.html;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}server {listen 8002;server_name localhost;# 字符集设置,避免中文乱码charset utf-8;# 代理前端应用的 /demo2/ 路径location /fileserver/ {proxy_pass http://localhost:8001/fileserver/;}location /api/ {proxy_pass http://localhost:8081;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
访问有点小瑕疵:
多了个/,不过不影响使用。
最佳实践
一体化
SPA借助ResourceHandler,足够使用了。
SPA使用hash路由模式,后端配置最简单。
分离版
base为/的打包模式
base为/的hash路由模式
转发版
一体版借助ResourceHandler配合./配置
一体版HASH路由模式带prefix
分离版base为/fileserver
分离版HASH路由模式
备注
配置nginx转发模式时,会发现需要同时配置/api的转发,如果只有一个应用倒无所谓,如果多个应用按照转发的方式配置到一个端口下,就要考虑api前缀的规划了,比如统一为 应用名-api,应用名/api,这样在转发的配置里各自进行配置,也不会乱。当然如果后台是同一个,那仍然可以配置成同一个。
细心的同学可能会注意到配置/nacos-proxy那个例子没有单独针对api再次配置nginx反向代理,而我在转发测试里却配置了。其实关键就在于axios的baseUrl配置,如果配置为/api,那你就需要配置/api的反向代理;如果配置为./api,那么他会跟随如/fileserver转发为/fileserver/api,前后端一体的情况就要求你的controller的url也是/fileserver/api;而分离版就要求你的前端同时也配置了/fileserver/api的反向代理,通过~^可提升他的优先级。
最后
可能有一些情况没有穷举到,但我想,其他情况都是相通的,也不需要每个情况都考虑的那么周到,具体有疑问的可以自行进行尝试,一试便知。