使用 React 和 Vert.x 开发单页面应用
本文档将向您展示如何使用 React 和 Vert.x 开发单页面应用 (SPA)。
您将构建什么
您将创建一个 React 前端,通过 HTTP 与 Vert.x 后端进行通信。
开发工作流
在开发 SPA 时,更新 Javascript、HTML 或 CSS 文件后能够立即获得反馈非常方便。使用 React,这需要您启动一个 npm
开发服务器,该服务器用于处理前端资源的请求
但是那些必须由 Vert.x 处理的请求呢?您将配置项目,使前端开发服务器将 API 请求代理到后端
创建项目
此项目的代码包含功能等效的 Maven 和 Gradle 构建文件。
使用 Maven
在您的 Maven POM 文件中添加 vertx-web
依赖
pom.xml
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${vertx.version}</version>
</dependency>
</dependencies>
然后添加 exec-maven-plugin
pom.xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<mainClass>io.vertx.howtos.react.BackendVerticle</mainClass>
</configuration>
</plugin>
使用 Gradle
假设您使用 Kotlin DSL 的 Gradle,添加 vertx-web
依赖
build.gradle.kts
dependencies {
val vertxVersion = "5.0.0.CR2"
implementation("io.vertx:vertx-web:${vertxVersion}")
}
然后配置应用程序主类
build.gradle.kts
application {
mainClass = "io.vertx.howtos.react.BackendVerticle"
}
通过 HTTP 暴露消息服务
让我们从后端服务开始。它将通过返回一个问候消息来处理 /api/message
路径上的请求
src/main/java/io/vertx/howtos/react/BackendVerticle.java
Router router = Router.router(vertx);
Route messageRoute = router.get("/api/message"); (1)
messageRoute.handler(rc -> {
rc.response().end("Hello React from Vert.x!"); (2)
});
router.get().handler(StaticHandler.create()); (3)
return vertx.createHttpServer()
.requestHandler(router)
.listen(8080);
1 | 定义了一个 Vert.x Web Route 来匹配 /api/message 路径上的 HTTP 请求 |
2 | Route 处理器用问候消息回复请求 |
3 | 需要 StaticHandler 来处理静态资源的请求 |
您可能想知道,如果前端开发服务器处理静态资源,为什么我们还需要一个 StaticHandler ?请记住,当整个应用程序构建并投入生产时,前端将与后端 HTTP 服务器捆绑在一起并由其提供服务。 |
在测试实现之前,BackendVerticle
需要一个 main
方法
src/main/java/io/vertx/howtos/react/BackendVerticle.java
public static void main(String[] args) {
Vertx vertx = Vertx.vertx(); (1)
vertx.deployVerticle(new BackendVerticle()).await(); (2)
System.out.println("Verticle started!");
}
1 | 创建一个 Vertx 上下文 |
2 | 部署 BackendVerticle |
您可以运行应用程序
-
直接从您的 IDE 中,或
-
使用 Maven:
mvn compile exec:java
,或者 -
使用 Gradle:
./gradlew run
(Linux, macOS) 或gradlew run
(Windows)。
要接收问候语,请打开您的终端并执行此命令
http :8080/api/message
您应该看到
HTTP/1.1 200 OK
content-length: 24
Hello React from Vert.x!
在浏览器中显示消息
我们有了一个完全可用的后端,现在可以创建前端了。为此,请使用 npx
运行 create-react-app
包
cd src/main
npx create-react-app frontend
这将
-
创建一个定义依赖项以及构建和运行脚本的
package.json
文件 -
安装依赖项
-
生成一个骨架应用程序
在本指南中,前端代码作为后端项目的一部分存在,位于 src 目录中。这更容易上手,特别是如果您的团队包含更多偏向后端的开发人员。但是,随着项目的增长,您可能更倾向于将前端和后端拆分为独立的模块。 |
这里对骨架应用程序不太感兴趣,所以我们将其删除
rm -rf frontend/src/*
然后打开您喜欢的编辑器并实现 React 前端
src/main/frontend/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
class Greeter extends React.Component { (1)
constructor(props) {
super(props);
this.state = { (2)
message: "Default message"
}
}
componentDidMount() { (5)
fetch("/api/message")
.then(response => response.text())
.then(text => this.setState({message: text}));
}
render() { (3)
return (
<div>
<span>{this.state.message}</span>
</div>
);
}
}
ReactDOM.render( (4)
<Greeter/>,
document.getElementById('root')
);
1 | 我们的前端由一个单独的 React Greeter 组件组成 |
2 | Greeter 组件持有状态,即要在浏览器中显示的消息 |
3 | 消息显示在一个简单的 HTML span 中 |
4 | Greeter 组件在网页中渲染 |
5 | 初始渲染后,会向后端发送一个 HTTP 请求;结果用于更新组件状态 |
最后但同样重要的是,您必须配置前端开发服务器以将 API 请求代理到后端。在您的编辑器中打开 package.json
文件并添加
src/main/frontend/package.json
"proxy": "https://:8080"
就是这样,打开一个终端并启动前端开发服务器
cd src/main/frontend
npm start
浏览器选项卡应该会自动打开并指向 https://:3000。
您应该看到
Hello React from Vert.x!
整合所有
当然,在生产环境中您不会启动前端开发服务器。因此,Maven POM(或 Gradle 构建)文件应配置为
-
运行前端构建
-
将静态文件复制到
src/main/resources/webroot
文件夹
您还记得第一节中的 StaticHandler 吗?它默认在 webroot 文件夹中查找静态文件。这就是为什么您必须将静态文件复制到 src/main/resources/webroot 的原因。 |
将这些插件添加到您的 Maven POM 文件中
pom.xml
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.7.6</version>
<configuration>
<nodeVersion>v22.12.0</nodeVersion>
<npmVersion>10.9.0</npmVersion>
<workingDirectory>src/main/frontend</workingDirectory>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install-node-and-npm</id>
<phase>generate-resources</phase>
<goals>
<goal>install-node-and-npm</goal> (1)
</goals>
</execution>
<execution>
<phase>generate-resources</phase>
<id>npm-install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments> (2)
</configuration>
</execution>
<execution>
<id>npm-run-build</id>
<phase>generate-resources</phase>
<goals>
<goal>npm</goal> (3)
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-to-webroot</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal> (4)
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/webroot</outputDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/frontend/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
1 | 在构建目录中下载 Node 和 npm 允许在 CI 上运行前端构建,即使它们可能不存在 |
2 | 使用 npm install 下载前端依赖项 |
3 | 创建前端的生产就绪构建 |
4 | 将静态文件复制到 src/main/resources/webroot |
如果您使用 Gradle,首先添加 Gradle NPM 插件
build.gradle.kts
import com.github.gradle.node.npm.task.NpmTask
plugins {
java
application
id("com.github.node-gradle.node") version "7.0.2"
}
然后配置类似于我们使用 Maven 所做的
build.gradle.kts
node {
version = "22.12.0"
npmVersion = "10.9.0"
download = true
nodeProjectDir = File("src/main/frontend")
}
val buildFrontend by tasks.creating(NpmTask::class) {
args = listOf("run", "build")
dependsOn("npm_install")
}
val copyToWebRoot by tasks.creating(Copy::class) {
from("src/main/frontend/build")
destinationDir = File("build/classes/java/main/webroot")
dependsOn(buildFrontend)
}
val processResources by tasks.getting(ProcessResources::class) {
dependsOn(copyToWebRoot)
}
确保所有之前的 npm
、mvn
或 gradlew
执行都已终止,然后启动 Vert.x 服务器
-
使用 Maven:
mvn compile exec:java
,或者 -
使用 Gradle:
./gradlew run
(Linux, macOS) 或gradlew run
(Windows)。
浏览到 https://:8080,您应该会看到
Hello React from Vert.x!
总结
本文档涵盖了
-
使用
create-react-app
创建一个新的 React 应用程序 -
运行一个前端开发服务器(用于实时重载),它将 API 请求委托给 Vert.x 后端
-
在生产环境中将前端静态文件与 Vert.x 类捆绑在一起