正式定档!QCon 北京站改期为2024年4月11-13日,地点:北京·国测国际会议会展中心 >>> 了解详情
写点什么

用 Spring Boot 打包你的 React 应用

  • 2020-03-31
  • 本文字数:3612 字

    阅读完需:约 12 分钟

用Spring Boot打包你的React应用

先讲一讲这篇文章的背景故事。之前我的团队需要在我们需求的基础架构上节省一些资金,并且由于我们要构建的这个应用程序中,大部分负载都会在客户端而非服务端上,所以我们决定试验一下能否将一个 Spring 应用程序与一个 React 应用结合起来,并打包成一个 war 文件。


这篇文章会告诉你如何将 Create React App 与 Spring Boot 结合使用,从而为你打包出单个 war 文件。


Spring Boot 和 Create React App 的基本功能介绍


  • Create React App 可帮助你非常快速地启动 React 项目。它为你提供了启动并尽快运行项目所需的全部基本功能。

  • Spring Boot 可以帮助你快速而轻松地启动和维护 Spring 应用程序。

步骤

1.目标

  • 在单一 war 文件中包含前端和后端,具有优化的生产构建

  • 保留 Create React App 所提供的好处,如热重载等

2.设置


附注:我选择的 IDE 是 IntelliJ。当使用 React 代码时,我通常会切换到 VS Code。你可以随意使用自己习惯的方法


  • 在 Github 上创建一个空的仓库,并添加自述文件、gitignore 和许可证等。

  • 转到(https://start.spring.io)创建你的 Spring 应用程序,并下载到本地。Group 和 Artifact 也可以随意设置。



GroupId:e.the.awesome


Artifact:spring-react-combo-app

3.将下载的项目解压缩到你的 git 目录中并提交。

你的 SpringReactComboAppApplication 看起来应该像这样。


package e.the.awesome.springreactcomboapp;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplicationpublic class SpringReactComboAppApplication extends SpringBootServletInitializer{
public static void main(String[] args) { SpringApplication.run(SpringReactComboAppApplication.class, args); }
}
复制代码

4.现在创建一个基本服务。

我们将其称为 DadJokesController。这应该在与 SpringReactComboAppApplication 文件所在的文件夹中创建。我知道这不是正确的 Rest API 格式,但现在暂时忽略它。


package e.the.awesome.springreactcomboapp;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class DadJokesController {    @GetMapping("/api/dadjokes")    public String dadJokes() {        return "Justice is a dish best served cold, if it were served warm it would be just water.";    }}
复制代码

5.在你的终端运行

mvn spring-boot:run
复制代码


然后在浏览器中检查http://localhost:8080/api/dadjokes。你应该会看到我们添加到控制器中的 dad joke。

6.要创建你的 React 应用,只需在根目录中运行

npx create-react-app basic-frontend-app
复制代码


你可以随心所欲地调用它,我这里只调用我的 basic-frontend-app

7.要运行前端应用程序:

cd basic-frontend-app<br>npm start
复制代码

8.解决代理问题

由于我们要将 Dad Jokes 服务集成到前端,因此首先我们要解决代理问题。你可能已经注意到了,你的服务从 localhost:8080 开始,而前端从 localhost:3000 开始。如果我们尝试从前端调用服务,具体取决于你的浏览器,你可能会收到一个 CORS 错误。



解决此问题的最简单方法是让前端代理处理从端口 3000 到 8080 的所有请求。此更改将在 package.json 文件中进行:


{  "name": "basic-frontend-app",  "version": "0.1.0",  "private": true,  "dependencies": {    "react": "^16.3.1",    "react-dom": "^16.3.1",    "react-scripts": "1.1.4"  },  "scripts": {    "start": "react-scripts start",    "build": "react-scripts build",    "test": "react-scripts test --env=jsdom",    "eject": "react-scripts eject"  },  "proxy": {    "/api": {      "target": "http://localhost:8080",      "ws": true    }  }}
复制代码


将以下内容添加到你的前端 App.js 文件中


import React, {Component} from 'react';import logo from './logo.svg';import './App.css';
class App extends Component {
state = {};
componentDidMount() { this.dadJokes() }
dadJokes = () => { fetch('/api/dadjokes') .then(response => response.text()) .then(message => { this.setState({message: message}); }); };
render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo"/> <h3 className="App-title">{this.state.message}</h3> </header> <p className="App-intro"> To get started, edit <code>src/App.js</code> and save to reload. </p> </div> ); }}
export default App;
复制代码


如果你也遇到了下图的这个错误,我的做法是:首先删除了 package-lock.json 文件;其次在 node_modules 文件夹中重新安装了 npm 包并再次运行;然后重新启动前端,问题就解决了。


9.你的应用程序现在应该看起来像这样。

你可以看到 dad jokes API 调用的结果。


10.创建生产版本

现在我们的基本前端和后端已经完成,该创建生产版本和单个 war 文件了。


< dependencies>下添加


<!-- https://mvnrepository.com/artifact/com.github.eirslett/frontend-maven-plugin --><dependency><groupId>com.github.eirslett</groupId><artifactId>frontend-maven-plugin</artifactId><version>1.6</version></dependency>
复制代码


在 pom 文件的< plugins>部分下,我们将添加以下命令,这些命令将在运行 mvn clean install 时执行以下操作。


  • npm 安装指定版本的 node

  • 运行我们前端的生产构建

  • 存放生产构建


<plugin>   <groupId>com.github.eirslett</groupId>   <artifactId>frontend-maven-plugin</artifactId>   <version>1.6</version>   <configuration>      <workingDirectory>basic-frontend-app</workingDirectory>      <installDirectory>target</installDirectory>   </configuration>   <executions>      <execution>         <id>install node and npm</id>         <goals>            <goal>install-node-and-npm</goal>         </goals>         <configuration>            <nodeVersion>v8.9.4</nodeVersion>            <npmVersion>5.6.0</npmVersion>         </configuration>      </execution>      <execution>         <id>npm install</id>         <goals>            <goal>npm</goal>         </goals>         <configuration>            <arguments>install</arguments>         </configuration>      </execution>      <execution>         <id>npm run build</id>         <goals>            <goal>npm</goal>         </goals>         <configuration>            <arguments>run build</arguments>         </configuration>      </execution>   </executions></plugin><plugin>   <artifactId>maven-antrun-plugin</artifactId>   <executions>      <execution>         <phase>generate-resources</phase>         <configuration>            <target>               <copy todir="${project.build.directory}/classes/public">                  <fileset dir="${project.basedir}/basic-frontend-app/build"/>               </copy>            </target>         </configuration>         <goals>            <goal>run</goal>         </goals>      </execution>   </executions></plugin>
复制代码


附注:对于你的插件来说,顺序正确是很重要的,因此请确保在复制构建文件执行之前执行 node/npm 安装

11.运行 mvn clean install

添加此命令后,运行 mvn clean install,并验证 target/classes 目录同时包含了前端文件和 Java 文件。这里你应该是一路畅通的。


最后看一下我的 pom 文件:


https://github.com/Emmanuella-Aninye/Spring-Boot-ReactJS-Starter/blob/master/pom.xml


这就是我的方法。如果你想看看 repo 或使用它,可以在我的 Github 上找到它:


https://github.com/Emmanuella-Aninye/Spring-Boot-ReactJS-Starter


延伸阅读:


https://hackernoon.com/package-your-react-app-with-spring-boot-a-how-to-guide-cdfm329w


2020-03-31 09:522878

评论

发布
暂无评论
发现更多内容

测试工程师如何收拾交接项目的烂摊子

陈磊@Criss

测试

搭建Prometheus+Grafana的云平台监控系统

学神来啦

云计算 Linux 运维 开发日志

必须加强对电商促销节的监管:保障普通消费者合法权益

石头IT视角

阿里云边缘容器服务ACK@Edge 通过33项测评,拿到“2021云边协同能力认证”

阿里巴巴中间件

公安情报研判分析系统解决方案,合成作战系统搭建

iOS开发21年6月面试总结(未完待续~)

iOSer

ios 面试 ios开发 iOS 知识体系

WebRTC学习—WebRTC详解

Linux服务器开发

音视频 WebRTC ffmpeg SRS流媒体服务器

WWDC21 给开发者最重要的7条新信息

阿里巴巴大淘宝技术

开发者 WWDC21

分布式能解决一切问题吗?百度架构师为你解答架构真正奥义!

Java架构师迁哥

WebRTC 传输安全机制第二话:深入显出 SRTP 协议

阿里云视频云

音视频 WebRTC 通信 流媒体开发 SRS流媒体服务器

终端架构深研,CodeDay 成都站等你

蚂蚁集团移动开发平台 mPaaS

flutter mPaaS Codeday Meetup

细细阅读,3张图带你理解,零拷贝,mmap和sendFile

奔着腾讯去

c++ Linux Mmap C++后台开发 网络io

新思科技宣布收购 Code Dx公司 添加软件漏洞关联、优先级和合并风险报告

InfoQ_434670063458

新思科技

2021年版,拼多多/阿里/今日头条/京东 Java面经大合集(含答案)

Java架构师迁哥

在线图片坐标拾取工具

入门小站

2021年5月云主机性能评测报告出炉,华为云跃居榜首

博睿数据

云主机 博睿数据 博睿指数

移动开发iOS,薪资如何?待遇怎样!

ios开发 iOS 知识体系

网易有道开源EMLL:高性能端侧机器学习计算库,大幅提高计算性能

有道技术团队

人工智能 机器学习 高性能计算 端侧AI

数据库设计的 10 个最佳实践

xcbeyond

数据库 数据库设计 6月日更

🌏【架构师指南】分布式技术知识点总结(下)

洛神灬殇

分布式 架构设计 6月日更

凭这份pdf每天花2小时学习,3个月后拿下阿里/美团/京东等offer

Java 程序员 架构 面试

Flink User-Defined Source

Alex🐒

flink 翻译 Flink扩展 flink1.13

专科小伙豪取三杀,斩获阿里、京东和蚂蚁Java岗offer的原因找到了!

北游学Java

Java 面试

5W1H聊开源之Who/When/Where——谁在何时何地“发明”了开源?

禅道项目管理

Linux 开源 软件

关于Redis分布式锁的那些事

Hex

redis 后端

阿里云中间件首席架构师李小平:企业为什么需要云原生?

阿里巴巴中间件

深入浅出 LVS 负载均衡(三)实操 NAT、DR 模型

UCloud技术

[译] 规避供应商以及特定版本的 VM Bugs

Antway

6月日更

谁说双非本就一定无缘阿里!(四年crud经验已拿下P7)面经分享

Java 程序员 架构 面试 计算机

80后自立门户,90后异军突起,中国投资新势力加速崛起 | 创业邦2021年40位40岁以下投资人重磅发布

创业邦

创业

第六课作业

杰语

用Spring Boot打包你的React应用_大前端_Emmanuella_InfoQ精选文章