【问题标题】:How to integrate a React webapp inside a spring boot Application with jar packaging如何将 React webapp 集成到带有 jar 包装的 Spring Boot 应用程序中
【发布时间】:2020-09-25 06:21:16
【问题描述】:

我们正在开发一个 react webapp 和一个 spring boot 应用程序(使用 maven 构建)。
React 应用程序(在 npm 上)和引导应用程序是分开运行的,但现在是时候将它们集成起来并将其放入 QA/staging 中了。
我们正在使用 webpack 来打包 react 应用程序。
启动应用程序是一个带有 REST API(由反应前端消耗)的单个模块,具有用于数据库持久性的休眠。

问题

  1. react 和 boot 应用程序的目录结构应该是什么?我们希望将整个应用程序(前端和后端)部署为 .jar(spring boot uberjar)
  2. 什么是 React 应用程序开发工作流程?每次进行小的 css、html 或 .js 更改时,无需运行 maven 和运行 java -jar 的工作流。

我在 Web 上找到了资源,其中 react 和 boot 应用程序位于单独的存储库/目录中,没有任何集成,这不是最佳的;我还没有找到一个资源,其中 webapp 资源和引导资源都在同一个目录树中,这也说明了开发生命周期和生产生命周期。

奖励:react 开发人员只知道 html/js/css。他们的 vscode/webstorm 项目中是否可能只有 react 应用程序资源?

【问题讨论】:

    标签: reactjs spring-boot webpack maven-3


    【解决方案1】:

    您可以在同一端口上运行 React 和 SpringBoot 并将它们打包为单个工件! 请按照我在此处解释的步骤进行操作,这应该可以帮助您启动并运行。 回答您的问题-

    1. 目录结构如下所示。两者都在同一个根目录下。
    2. 关于 react 应用程序开发工作流程 - 您可以按照开发前端 react 项目的方式进行开发,热重载(保存文件,更改将自动反映)和有意义的错误消息。您必须使用代理进行通信。

    这是我要去的演示项目的Github链接 在这里解释

    Spring Boot 可以提供来自 src/main/resources/static 文件夹的静态内容。我们将利用 Spring Boot 的上述特性来服务于 react 项目的单页。我们将从目标目录中的静态文件夹中提供一个 html 页面,而不是在源目录中。

    项目结构-

    首先,使用https://start.spring.io 创建一个spring boot 项目。添加 Web 依赖项。将 groupId 和 artifactId 设置为您想要的任何内容。生成项目并将其解压缩到您的项目目录中。

    或者,如果您使用的是 Spring Tools Suite,您只需点击 File->New->Spring Starter Project 并提及创建 Spring Boot 项目所需的详细信息。

    src/main 中的 frontend 文件夹应该让您的 react 应用程序使用 create-react-app 构建。

    所以,有两个步骤-

    1. 创建前端的生产版本。
    2. 将生产版本复制到 ${target/classes/}。

    我们将使用两个 maven 插件和 Thymleaf

    1. frontend-maven-plugin 第 1 步。
    2. maven-resources-plugin 第 2 步。

    对于frontend-maven-plugin 在步骤 1-- 如果您仔细查看 pom.xml 那里我提到了 src 目录 frontend-maven-plugin 将从那里获取文件,创建生产构建并将内容放在提到的输出目录中(在src/main/frontend/build 内)。

     <workingDirectory>${frontend-src-dir}</workingDirectory>
     <installDirectory>${project.build.directory}</installDirectory>
    

    对于第 2 步的 maven-resources-plugin-- 它将采用 frontend-maven-plugin 刚刚创建的生产版本并将其放置在您的根目录中,然后是 target/classes/static

    然后我们将使用 Thymleaf 来提供来自 target/classes/static 的静态内容,并使用控制器中的休息端点。否则你必须输入html file的名字,比如http://localhost:8080/index.html

    您的 pom.xml 应该如下所示-

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.2</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.springreact</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demo</name>
        <description>Run React Frontend and SpringBoot Backend on the same port.</description>
        <properties>
            <java.version>1.8</java.version>
            <frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
            <node.version>v14.15.4</node.version>
            <yarn.version>v1.16.0</yarn.version>
            <frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId> 
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>com.github.eirslett</groupId>
                    <artifactId>frontend-maven-plugin</artifactId>
                    <version>${frontend-maven-plugin.version}</version>
    
                    <configuration>
                        <nodeVersion>${node.version}</nodeVersion>
                        <yarnVersion>${yarn.version}</yarnVersion>
                        <workingDirectory>${frontend-src-dir}</workingDirectory>
                        <installDirectory>${project.build.directory}</installDirectory>
                    </configuration>
    
                    <executions>
                        <execution>
                            <id>install-frontend-tools</id>
                            <goals>
                                <goal>install-node-and-yarn</goal>
                            </goals>
                        </execution>
    
                        <execution>
                            <id>yarn-install</id>
                            <goals>
                                <goal>yarn</goal>
                            </goals>
                            <configuration>
                                <arguments>install</arguments>
                            </configuration>
                        </execution>
    
                        <execution>
                            <id>build-frontend</id>
                            <goals>
                                <goal>yarn</goal>
                            </goals>
                            <phase>prepare-package</phase>
                            <configuration>
                                <arguments>build</arguments>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>position-react-build</id>
                            <goals>
                                <goal>copy-resources</goal>
                            </goals>
                            <phase>prepare-package</phase>
                            <configuration>
                                <outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
                                <resources>
                                    <resource>
                                        <directory>${frontend-src-dir}/build</directory>
                                        <filtering>false</filtering>
                                    </resource>
                                </resources>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    

    这是控制器代码。

    package com.springreact.demo.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    public class IndexController {
    
        @GetMapping("")
        public ModelAndView home() {
            ModelAndView mav=new ModelAndView("index");
            return mav;
        }
    
    }
    

    如果您按照上述步骤操作,您应该会看到您的 React 应用程序正在http://localhost:8080/ 上启动。

    有关更多详细信息,您可以查看我在上面写的博客。以下是两个不同平台上的博客链接-

    开发社区-https://dev.to/arpan_banerjee7/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-14pa

    中等-https://medium.com/codex/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-a790c9e10ac1

    【讨论】:

    • 非常感谢您!一直试图弄清楚这一天。我是一位经验丰富的 Java 开发人员,但对 Javascript 框架不熟悉。很难找到有关如何执行此操作的明确说明
    • 感谢阿潘!我正在开始将前端从 Spring Boot 应用程序分离到 webpack 构建的前端(很可能是 React)的过程,目前我无法使用两个单独的 jar 文件将它们拆分为 maven 模块。您的解决方案非常适合我的项目,并且解释得很好!
    【解决方案2】:

    我建议创建多模块 maven 项目,其中一个模块是 spring-boot 应用程序,第二个模块是 react 应用程序。要将其放入 uber jar,请将 react 应用程序打包到由 maven 构建的 webjar 中。 构建也可以通过 maven 和适当的插件来完成。

    所以:

    1. 在项目的子目录中创建普通的 react 应用程序(通过 npm 等构建)
    2. 添加到这个应用程序 pom.xml 这将 compile javascript on maven compilepack it into proper webjar structure
    3. 在 spring-boot 模块中添加 react 一个作为正常的 maven 依赖项。 Check out this tutorial

    这将允许您将所有内容都作为一个 uber jar 应用程序。另一方面,前端人员可以像使用任何其他 React 应用程序一样使用 React 模块。

    【讨论】:

    • 问题是这是最佳实践吗?把两个都放在一个罐子里?还是在机器上分别部署react和spring boot更好?
    • 这取决于你的需要。
    【解决方案3】:

    我发现这篇文章可能会回答您的问题。它展示了如何开发 react 前端和 spring boot 后端,然后将它们合并到一个单独的 jar 文件中进行部署。

    https://medium.com/@mukundmadhav/build-and-deploy-react-app-with-spring-boot-and-mysql-6f888eb0c600

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-18
      • 2016-11-08
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 2020-03-20
      • 2015-12-26
      相关资源
      最近更新 更多