分离前端和 API 服务

 

介绍

  JHipster is a “full-stack” development tool, and its goal is to make you work efficiently with your front-end code (Angular/React) and your back-end code (Spring Boot).

However, it is a common requirement to separate the front-end and the back-end codes, typically because they are developed by different teams and have a different lifecycle.

请注意 这并非 JHipster 默认的工作方式:这并不复杂,并且运行正常,但毕竟是属于高级主题。如果你是刚刚接触 JHipster,我们还是推荐你使用标准方式开始。

分别创建前端和后段程序

  You can choose to generate only a JHipster back-end or JHipster front-end application. At generation time, this is only a matter of choosing flags which are described in our application generation documentation:

  • jhipster --skip-client 会只创建后段应用 (这就类似一个典型的微服务应用)
  • jhipster --skip-server 将会创建前端应用

目录结构

  JHipster 使用标准的 Maven 目录结构。在后端应用结构上,参考 Maven 标准目录结构说明.

至于前端,有两个目录你需要了解:

  • src/main/webapp 是存放客户端应用代码的地方
  • target/www 是客户端应用打包的地方

如果你的团队分为前端和后端,你有两种做法:

  • 两个团队可以在一个项目上工作。As the directories are separated, there won’t have much conflicts between teams. To make things even cleaner, both teams could work on separate branches.
  • 前端代码可以存在一个单独的 Git 项目里,然后以 Git 子模块的形式导入后端项目。这样做需要删掉客户端打包脚本,这非常简单。

HTTP 请求路由及缓存

  Once the front-end and back-end have been separated, the issue will be how to handle HTTP requests:

  • All API calls will use a /api prefix. If you are using Angular, there is also a specific SERVER_API_URL constant, defined in the webpack.common.js configuration, that can enrich this prefix. For example, you can use "http://api.jhipster.tech:8081/" as a back-end API server (If you do this, please read our documentation on CORS below).
  • Calls to / serve static assets (from the front-end), which should not be cached by the browser.
  • Calls to /app (which contains the client-side application) and to /content (which contains the static content, like images and CSS) should be cached in production, as those assets are hashed.

使用 BrowserSync

In dev mode, JHipster uses BrowserSync for hot-reload of the front-end application. BrowserSync has a proxy (here is its documentation) that will route requests from /api to a back-end server (by default, http://127.0.0.1:8080).

This only works in dev mode, but this is a very powerful way of accessing different API servers from the front-end.

使用 CORS

CORS (Cross-origin request sharing) allow to access different back-end servers with the same front-end, without configuring a proxy.

这里有一个简单的解决方案,但是在生产环境中并不是很安全。

JHipster 提供 out-of-the-box a CORS 配置:

  • CORS 可以用 jhipster.cors 属性设置, 这里 有定义描述:the JHipster common application properties (译注:)
  • It is enabled by default in dev mode for monoliths and gateways. It is disabled by default for microservices as you are supposed to access them through a gateway.
  • 生产环境 prod 中默认关闭, for security reasons.

使用 NGinx

Another solution to separate the front-end and back-end codes is to use a proxy server. This is very common in production, and some teams also use this technique in development.

This configuration will change depending on your specific use-case, so this cannot be automated by the generator, here is below a working configuration.

Create a src/main/docker/nginx.yml Docker Compose file:

version: '2'
services:
  nginx:
    image: nginx:1.13-alpine
    volumes:
    - ./../../../target/www:/usr/share/nginx/html
    - ./nginx/site.conf:/etc/nginx/conf.d/default.conf
    ports:
    - "8000:80"

This Docker image will configure an NGinx server, that reads the static assets from target/www: this is where the JHipster front-end application is generated by default. In production, you will probably have a specific folder for this.

It also reads a ./nginx/site.conf file: this is a NGinx-specific configuration file. Here is a sample site.conf:

server {
    listen 80;
    index index.html;
    server_name localhost;
    error_log  /var/log/nginx/error.log;

    location / {
        root /usr/share/nginx/html;
    }
    location /api {
        proxy_pass http://api.jhipster.tech:8081/api;
    }
    location /management {
        proxy_pass http://api.jhipster.tech:8081/management;
    }
    location /v2 {
       proxy_pass http://api.jhipster.tech:8081/v2;
    }
    location /swagger-ui {
        proxy_pass http://api.jhipster.tech:8081/swagger-ui;
    }
    location /swagger-resources {
        proxy_pass http://api.jhipster.tech:8081/swagger-resources;
    }
}

This configuration means that:

  • NGinx will run on port 80
  • It will read the static assets in folder /usr/share/nginx/html, and
  • It will act as a proxy from /api to http://api.jhipster.tech:8081/api

This configuration will require some tuning depending on your specific needs, but should be a good enough starting point for most applications.