天天看點

用 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 也可以随意設定。
用 Spring Boot 打包你的 React 應用

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;

@SpringBootApplication
public 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;
@RestController
public 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.在你的終端運作

用 Spring Boot 打包你的 React 應用

然後在浏覽器中檢查

http://localhost:8080/api/dadjokes

。你應該會看到我們添加到控制器中的 dad joke。

6.要建立你的 React 應用,隻需在根目錄中運作

用 Spring Boot 打包你的 React 應用

你可以随心所欲地調用它,我這裡隻調用我的 basic-frontend-app

7.要運作前端應用程式:

用 Spring Boot 打包你的 React 應用

8.解決代理問題

由于我們要将 Dad Jokes 服務內建到前端,是以首先我們要解決代理問題。你可能已經注意到了,你的服務從 localhost:8080 開始,而前端從 localhost:3000 開始。如果我們嘗試從前端調用服務,具體取決于你的浏覽器,你可能會收到一個 CORS 錯誤。

用 Spring Boot 打包你的 React 應用

解決此問題的最簡單方法是讓前端代理處理從端口 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 包并再次運作;然後重新啟動前端,問題就解決了。

用 Spring Boot 打包你的 React 應用

9.你的應用程式現在應該看起來像這樣。

你可以看到 dad jokes API 調用的結果。

用 Spring Boot 打包你的 React 應用

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://yqh.aliyun.com/zhibo

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-03-31

本文作者:Emmanuella

本文來自:“

InfoQ

”,了解相關資訊可以關注“