使用Java和ReactJS服务器端渲染的微服务UI前端

Dav*_*vid 6 java reactjs microservices server-side-rendering

我目前的设计是让客户端使用浏览器连接到我的(Java)Web API网关,Web API网关将调用每个(Java)微服务来获取他们的JSON数据并将其返回到在客户端上发出请求的UI组件.

唯一的客户端呈现将来自每个ReactJS UI组件,用于重复发送到网关的请求.

在服务器端,将在发送回客户端之前呈现完整的HTML视图.

Client browser

     ? (Request Dashboard View)

Web API Gateway

     ? (Request microservice JSON data)

Microservice A JSON Data
Microservice B JSON Data
Microservice C JSON Data
Microservice D JSON Data

     ? (Return JSON Data to gateway)

Web API Gateway

     ? (Render HTML and return to Client)

Client browser

     ? (ReactJS UI Components request data from API Gateway)
Run Code Online (Sandbox Code Playgroud)

这是不清楚的地方,是否最好让每个UI组件与Web API网关或它来自的微服务器进行通信以获取数据?

注意事项

  • 让UI组件与Web API Gateway通信似乎是合理的,但会将微服务耦合到网关,这意味着在微服务上公开新的API,网关也需要更新.
  • 让UI组件直接与其微服务通信以获取数据,这样就无需更新Web API网关,从而减少了它们的耦合.但是这会将微服务暴露给来自客户端浏览器的外部调用.

设计决策

  • 在API网关中具有UI组件创建UI整体,而不是让每个微服务负责其自己的UI组件.使用单片方法简化了解决方案,并且还避免了在客户端请求特定视图时必须聚合每个微服务UI组件的复杂性.

工具:

  • Java的
  • 犀牛
  • Dropwizard
  • ReactJS
  • 摇篮
  • 的WebPack
  • 的NodeJS
  • NPM

如何使用Java和ReactJS在Web API网关上聚合多个微服务ui组件,然后将此预呈现的HTML数据与JavaScript应用程序一起提供给客户端?

有用的参考:

Dav*_*vid 3

问题

如何在 Web API 网关上的服务器端渲染期间聚合 ReactJS UI 组件。

解决方案

使用像Mustache这样的模板框架来注入每个 ReactJS 组件服务器端渲染的 HTML 输出,然后将此 HTML 提供回客户端。

Github 存储库https://github.com/damorton/dropwizardheroku-webgateway

服务器端

我在 Web API 网关上实现的解决方案首先从微服务请求 JSON 数据,然后渲染 ReactJS 组件,同时将来自微服务的 JSON 数据注入为Props. 一旦我有了完全渲染的 ReactJS 组件,并将数据作为 HTML 字符串,我就使用 Mustache 模板将完全渲染的 ReactJS 组件 HTML 注入到 Mustache 模板中,然后将其返回给客户端。

WebGatewayResource.java

@GET
@Produces(MediaType.TEXT_HTML)
public IndexView index() throws IOException {

    // Get events json data from Events microservice
    ApiResponse events = getEventsJsonData();

    // Render the Events component and pass in props
    @SuppressWarnings("unchecked")
    List<Object> eventsProps = (List<Object>) events.getList();
    String eventsComponent = this.nashornController.renderReactJsComponent(kEventsUiComponentRenderServerFunction, eventsProps);

    IndexView index = new IndexView(eventsComponent);
    return index;
}
Run Code Online (Sandbox Code Playgroud)

注意: Dropwizard 围绕 Mustache 模板执行了很多魔法,因此所需要做的就是创建一个index.mustache文件并在构造类时引用它IndexView。将其返回View给客户端告诉 Dropwizard 渲染视图并返回 HTML。

索引.胡子

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Dropwizard Heroku Event Service</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom-server.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.1/axios.min.js"></script>
</head>
<body>
  <h1>Events</h1>
  <div id="events">{{{eventsComponent}}}</div>
  <script type="text/javascript" src="assets/js/bundle.js"></script>
  <script type="text/javascript" src="assets/js/client.js"></script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

客户端

在客户端,为了解决由于最初安装 ReactJS 组件时不可用而导致客户端和服务器端呈现的 HTML 不同的问题,在页面加载时调用 JavaScript 函数来请求 JSON来自网关的数据。

客户端.js

var loadEventsFromServer = function(eventsUrl) {
    axios.get(eventsUrl).then(function(res) {
        var data = res.data.list;       
        renderClientEvents(data);
    });
};

loadEventsFromServer('https://domain.webapigateway.com/events');
Run Code Online (Sandbox Code Playgroud)

ReactJS

挂载组件时,客户端 HTML 不会重新渲染,React 知道服务器端渲染中已经存在的 HTML,并且仅在挂载时为每个组件添加事件侦听器。这允许 React 单独更新其组件,并且还可以利用服务器端渲染。