React.js+NPM前端与Spring Boot后端同端口启动需求(保持分层)
我完全理解你的需求——不想把前端和后端用Maven绑定在一起,保持各自独立的开发流程,同时又要让它们在同一端口运行,方便前端用相对路径调用API。下面分开发环境和生产环境两种场景给你具体方案:
一、开发环境方案(保持前后端独立开发,同一端口访问)
方案1:React开发服务器代理(推荐,配置简单)
React的create-react-app自带代理功能,只需要在前端项目的package.json里加一行配置,就能让前端的请求自动转发到后端,同时你可以用相对路径写API请求:
在React项目的
package.json末尾添加:"proxy": "http://localhost:8080"(这里假设你的Spring Boot后端跑在8080端口,可根据实际情况修改)
启动后端:在IntelliJ里运行Spring Boot项目,确保它在目标端口正常服务。
启动前端:在React项目根目录执行
npm start,前端会跑在默认的3000端口,但此时你在前端代码里写相对路径的API请求,比如:fetch('/api/users') // 会自动转发到http://localhost:8080/api/users这种方案下,前端依然是完全独立的项目,不用和后端做任何整合,只是通过代理实现了相对路径调用API的需求。
方案2:Spring Boot转发前端资源到React开发服务器
如果你希望所有请求都通过Spring Boot的端口访问(包括前端页面),可以让Spring Boot把静态资源请求转发到React的开发服务器:
在Spring Boot项目里添加一个配置类处理跨域,同时添加控制器转发路由:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("*"); } }import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class ForwardController { // 转发所有非API请求到React开发服务器,替换成你的前端路由 @GetMapping(value = {"/", "/about", "/dashboard"}) public String forwardToReact() { return "forward:http://localhost:3000"; } }启动后端(8080端口)和前端(3000端口),此时访问
http://localhost:8080就会看到React页面,前端的API请求用相对路径也会直接打到后端的8080端口,完美实现同一端口访问,同时前后端依然独立开发。
二、生产环境方案(打包前端,由Spring Boot静态服务)
当你要部署项目时,只需要把React打包后的静态文件交给Spring Boot托管,就能在同一端口运行:
在React项目根目录执行
npm run build,会生成一个build文件夹,里面是所有打包好的静态资源(HTML、CSS、JS等)。把
build文件夹里的所有内容复制到Spring Boot项目的src/main/resources/static目录下(如果没有static文件夹就新建一个)。启动Spring Boot项目,访问
http://localhost:8080就能直接看到React页面,前端的API请求用相对路径(比如/api/users)会直接调用后端接口,完全不需要跨域配置,因为它们在同一端口下。
这种方式下,前端依然是独立开发的——你可以在开发时单独维护React项目,只有在部署时才把打包后的文件交给Spring Boot,完全符合你“前端作为独立层”的要求。
内容的提问来源于stack exchange,提问作者Jurass

