Vue + SpringBoot 前后端分离项目用Maven自动打包合并为单体项目

Vue + SpringBoot 前后端分离项目用Maven自动打包合并为单体项目

前端打包模块详细文档 https://github.com/eirslett/frontend-maven-plugin
本项目地址 https://gitee.com/luvying/vue-maven-demo

前言

对于一些小项目,觉得没必要通过前后端分离进行部署,太浪费服务器资源了,但是用jQuery、bootstrap等又不能做到像前端框架那样能够模块化开发,因此就想着能不能用前后端分离的方式开发项目,开发完毕后把前端合并到后端去成为一个单体应用。通过查找,有人说前端开发完把编译好的文件copy到后端static目录中…太麻烦了…后来找到有个maven插件frontend-maven-plugin可以实现这个需求,于是参考了多篇博文,踩了些坑,做了这个demo,以后有这个需求来这个demo中copy代码就阔以了=。=

项目结构

vue-maven-demo
├──springboot-api
└── vue-web

在这里插入图片描述

pom配置

重点在于pom的配置

vue-maven-demo.pom

父模块的配置

	<groupId>com.luvying</groupId>
    <artifactId>vue-maven-demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>springboot-api</module>
        <module>vue-web</module>
    </modules>

    <properties>
        <spring.boot.version>2.6.1</spring.boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

springboot-api

子模块:后端模块的配置

    <parent>
        <artifactId>vue-maven-demo</artifactId>
        <groupId>com.luvying</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>springboot-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-api</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <!-- 前端项目编译后的dist目录路径 -->
        <frontend-project-dist-dir>${project.parent.basedir}/vue-web/dist</frontend-project-dist-dir>
        <java.version>1.8</java.version>
        <maven-clean-plugin>3.1.0</maven-clean-plugin>
        <maven.resource.version>3.1.0</maven.resource.version>
    </properties>

    <dependencies>
        <!-- 需要依赖前端模块,否则无法打包进后端系统,前端模块将会打一个空的jar包 -->
        <dependency>
            <groupId>com.luvying</groupId>
            <artifactId>vue-web</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
                <!--解决打包后,执行java -jar 命令,找不到主清单属性-->
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- 插件maven-clean-plugin,用于在编译前,清除之前编译的文件、文件夹等,避免残留之前的内容 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>${maven-clean-plugin}</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <!-- 前端资源目录,即:存放前端包目录-->
                            <directory>src/main/resources/static</directory>
                        </fileset>
                        <fileset>
                            <!-- Vue项目打包自动生成的dist目录 -->
                            <directory>${frontend-project-dist-dir}</directory>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

            <!--资源插件,主要为了从前端项目里复制打包好的文件到springboot项目-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>${maven.resource.version}</version>
                <executions>
                    <execution>
                        <id>copy static</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <!-- 复制前端打包文件到这里 -->
                            <outputDirectory>src/main/resources/static</outputDirectory>
                            <overwrite>true</overwrite>
                            <resources>
                                <resource>
                                    <!-- 从前端打包的目录dist进行指定文件、文件夹内容的复制-->
                                    <directory>${frontend-project-dist-dir}</directory>
                                    <includes>
                                        <!-- 具体根据实际前端代码、及目录结构进行配置-->
                                        <include>css/</include>
                                        <include>fonts/</include>
                                        <include>img/</include>
                                        <include>js/</include>
                                        <include>favicon.ico</include>
                                        <include>index.html</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

vue-web

子模块:前端模块的配置

    <parent>
        <artifactId>vue-maven-demo</artifactId>
        <groupId>com.luvying</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>vue-web</artifactId>

    <properties>
        <!--前端打包-->
        <maven-frontend-plugin.version>1.12.0</maven-frontend-plugin.version>
        <maven-frontend-plugin.nodeVersion>v16.13.1</maven-frontend-plugin.nodeVersion>
<!--        <maven-frontend-plugin.nodeVersion>v9.9.0</maven-frontend-plugin.nodeVersion>-->
<!--        <maven-frontend-plugin.npmVersion>6.9.0</maven-frontend-plugin.npmVersion>-->
        <maven-frontend-plugin.npmVersion>8.1.2</maven-frontend-plugin.npmVersion>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>${maven-frontend-plugin.version}</version>
                <executions>
                    <execution>
                        <id>install node and npm</id>
                        <goals>
                            <goal>install-node-and-npm</goal>
                        </goals>
                    </execution>
                    <!-- Install all project dependencies -->
                    <execution>
                        <id>npm install</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>
                    <!-- Build and minify static files -->
                    <execution>
                        <id>npm run build</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>run build</arguments>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <nodeVersion>${maven-frontend-plugin.nodeVersion}</nodeVersion>
                    <npmVersion>${maven-frontend-plugin.npmVersion}</npmVersion>
                    <!-- 若不方便访问官网,可手动设置镜像地址-->
                    <nodeDownloadRoot>https://npm.taobao.org/mirrors/node/</nodeDownloadRoot>
                    <npmDownloadRoot>https://registry.npm.taobao.org/npm/-/</npmDownloadRoot>
                </configuration>
            </plugin>
        </plugins>
    </build>

相关说明

把前端代码打包进后端,主要是几个流程(结合上面的pom看更清晰):

  1. frontend-maven-plugin下载node和npm到本地,然后将前端代码进行编译,编译完成后文件在vue-web/dist中(所以本地可以不需要有node环境也能够编译)
  2. maven-clean-plugin把后端项目中src/main/resources/static清空
  3. maven-resources-plugin去前端项目拿到vue-web/dist将它复制到后端项目src/main/resources/static
  4. 接下来的流程就和maven正常打包一样了

自己的项目目录有变化的话,修改pom中相应的目录路径即可
打包时,在父模块vue-maven-demo执行maven install,生成的jar包会在springboot-api\target下而不是vue-web\target下,因为vue-web是为了编译前端文件而打了个空包而已

前端项目

本文以vue为例(其他前端项目类似),用vue-cli生成了一个vue项目,简单写了获取后端数据、前端路由的例子,经测试,前端打包进后端后功能正常
在这里插入图片描述
前端项目结构如下
在这里插入图片描述
详细见源码

前端开发与部署问题

前端在开发完成后要编译成静态文件合并到后端中去前后端为一整个系统,而前后端在开发时又是两个分开的系统,为了防止axios打包后无法访问后端,就需要配置开发时axios发送到后端的端口
如下图vue.confie.js配置前端8000端口,axios访问后端api为8080端口,而打包后前端合并到了后端,那么此时整个系统就是8080端口了
在这里插入图片描述

原来以为前端路由在打包后会出现异常,经过尝试后前端路由正常,也不用写啥了=。=

为了实现这个功能参考过一些文章,东凑凑西凑凑,有需要自取哈
https://www.cnblogs.com/LUA123/p/11189069.html
https://github.com/Mysakura/boot-vue-parent
https://juejin.cn/post/6978764604142780446
https://juejin.cn/post/6977316219615445022