SpringBoot和VUE源码直接整合打包成jar的踩坑记录
作者:喵喵@香菜
一、前言
spring boot是要打成jar包运行的,项目采用了前(VUE)后(SpringBoot)端完全分离,开发完成后需要整合到一起发布,这就要引出这篇博客的由来了;一开始的时候是前端VUE开发完成后打成dist包然后发给我(前后端不在一起开发),我拿到dist包后解压然后放到springboot的static目录下。
然后将项目打成jar包。
最后部署,一次两次没问题,但是如果是联调阶段,前端改了东西就会很麻烦。
因为我们不在一起工作,团队的git地址不是同的。
项目经理提出:把这两个一起打包,你研究一下,能到做吧?
这时我走向了楼顶,好的,博客结束,人生结束。。。。(搞笑一下)
程序员的字典里没有不字!去网上搜,别说还真有这玩意(比人才疏学浅,工作没多长时间,所以对我来说算是个难题)但是原博客里有坑啊,弄过来以后没达到预期效果啊,这个坑就是我长进的地方了。
二、环境介绍
一个springBoot项目、maven、VUE前端源码、本地需要安装node环境、IDEA
三、踩坑
加个思路说明吧:通过maven打包jar包时,通过maven调用node命令先将VUE打包,然后将打包好的东西通过复制的方式到指定目录;这个是网上其他博客的思路,我一开也是进行这种,后面进行了改进。
先踩别人踩过的脚印。
1)先介绍一下目录结构
如下如
说明一下:springBoot的是目录结构是java和resource,在main目录下创建一个文件夹web(名字你自己定,但是下面配置maven的时候要对应上);
扩展:在IDEA中开发vue,可以安装UVE.js插件,这个安装教程我就不写了,网上有。
2)要介绍一下VUE打包流程
首先源码是我要过来以后直接粘贴到的web文件夹下,但是没有node_modules这个文件夹,因为这个文件夹一般很大(而且好像默认也会忽略这个文件夹),所以前端没有粘给我。
这个时候就需要先install
拿到源码后npm命令总结如下:npm install (安装相关modules)
npm run build (打包)
如果是npm镜像为淘宝的那个的话,npm和cnpm等效。
3)在项目中的pom文件中添加插件
pom文件如下图:
先声明:VUE源码没有node_module,所以是要第一步执行的,第二部是buildVue,第三步是复制打包的东西到指定目录。
这个顺序很重要,就像人生一样,凡事总要有个顺序。。。扯远了,之所以是因为强调顺序,是因为我采的坑就是顺序问题。
pom文件来了,如下图:
<build> <plugins> <!--SpringBoot和VUE整合打包--> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <!--1、maven执行node的install命令--> <execution> <id>exec-cnpm-install</id> <!--这个阶段很重要,不能乱写,install必须要为第一阶段--> <phase>initialize</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>cnpm</executable> <arguments> <argument>install</argument> </arguments> <!--执行install命令的目录--> <workingDirectory>${basedir}/src/main/web</workingDirectory> </configuration> </execution> <!--2、install完成后build--> <execution> <id>exec-cnpm-run-build</id> <!--阶段一定要在复制之前,且在打包和复制都在编译之前--> <phase>initialize</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>cnpm</executable> <arguments> <argument>run</argument> <argument>build</argument> </arguments> <workingDirectory>${basedir}/src/main/web</workingDirectory> <addOutputToClasspath>true</addOutputToClasspath> </configuration> </execution> </executions> </plugin> <!--3、复制打包好的文件到指定目录--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>${project.build.sourceEncoding}</encoding> </configuration> <executions> <execution> <id>copy-spring-boot-webapp</id> <phase>initialize</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>utf-8</encoding> <outputDirectory>${basedir}/src/main/resources/static</outputDirectory> <resources> <resource> <directory>${basedir}/src/main/web/dist</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> </plugins> </build>
说明:这个地方需要说一下maven的打包的阶段,然后配合上上面说明的顺序才能一步打包成jar。
4)扩展—maven的默认生命周期
以下是按照先后顺序排列的。
default生命周期是最核心的,它包含了构建项目时真正需要执行的所有步骤。
validate initialize generate-sources process-sources generate-resources process-resources:复制和处理资源文件到target目录,准备打包; compile:编译项目的源代码; process-classes generate-test-sources process-test-sources generate-test-resources process-test-resources test-compile:编译测试源代码; process-test-classes test:运行测试代码; prepare-package package:打包成jar或者war或者其他格式的分发包; pre-integration-test integration-test post-integration-test verify install:将打好的包安装到本地仓库,供其他项目使用; deploy:将打好的包安装到远程仓库,供其他项目使用;
5)坑在哪?
坑就在网上的博客只是在阶段上粘贴了一段如:
代码下
<execution> <id>copy-spring-boot-webapp</id> <!-- here the phase you need --> <phase>initialize</phase> <goals> <goal>copy-resources</goal> </goals>
像我这种经过这种坑才知道maven生命周期的人是注定要踩进去的。踩的坑多了,世界便没有了坑。。。
像这个initialize 这里填入的参考上面贴出的maven默认生命周期,因为打包是将target下的东西最后压缩成jat ,也就是编译后的东西,所以我们的install,build和复制操作都应该在compile阶段之前。所以选择在了
第一阶段initialize。当初网上博客写的基本上全都是prepare-package阶段,这tm让我这个渣渣调了三个小时,最后将坑zhan于马下。也不知道他们那些是真的一步打包成功了还是故意留坑。
6)关于标签
这个是将插件的执行绑定到maven执行的时候生命周期。关于这个生命周期有一篇博客,我转载了,列举的很清楚。
7)虽然解决了坑
但是解决完思考一下,步骤其实可以是可以简化的,就比如那个复制过程。以及install过程。下个标题介绍简化。
8)如果你在maven里配置install、build和copy第一次的时间会很长
而且还不一定会成功。可以根据需要将阶段优化。主要是因为maven执行node命令的时候,node那个命令很慢。
四、简化
1)install这个建议最好在maven配置中去掉
时间慢是一部分原因,另一部分原因就是,如果你以后要重新打jar的话,还是会执行install,这个install只需要一次就够了,所以建议这个install不要加。
在将源码复制的时候要一份node_modlues或者自己学着在cmd里先执行完install命令。
如果node环境没问题,因为这个只需要成功执行一次就够了。
另一种情况就是如果项目一开始在搭建的时候,vue和springboot都在一个目录下的话,也就是初始化vue的时候你肯定执行过install命令。
另外说明一点就是如果Vue前端开发中添加了新的modules,你就需要执行install命令,(而且版本控制的时候没有提交这个新的modules),作为一个java开发工程师在cmd里执行一下子还是行的吧,毕竟你想一起打包的话,也要安装node环境,只需要在vue目录下执行 npm install 就可以了,没什么难度。
2)build是必须要的
如果我们把build好的包直接build到指定目录,这样是不是就不在需要copy这个插件,对吧,所以我的简化思路就是直接build到指定目录好了。
五、简化过程
1)思路
先在cmd中执行install(因为install不是主要的,只有在vue中添加了新的Modules和初始化时才需要),所以去掉这个plugin;
主要就是执行run build,所以将复制那一步也省略掉。
2)修改pom文件中的配置
修改后如下(其实就是将install和copy去掉了):
<build> <plugins> <!--SpringBoot和VUE整合打包--> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <!--2、install完成后build--> <execution> <id>exec-cnpm-run-build</id> <phase>initialize</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>cnpm</executable> <arguments> <argument>run</argument> <argument>build</argument> </arguments> <workingDirectory>${basedir}/src/main/web</workingDirectory> <addOutputToClasspath>true</addOutputToClasspath> </configuration> </execution> </executions> </plugin> </plugins> </build>
说明:${basedir}/src/main/web是放置整个VUE源码的地方,当去掉复制这一个plugin以后,就需要在VUE源码里进行修改,也就是设置build的时候直接放到springBoot的static下。
3)项目目录结构
如下:
说明:static是放置静态资源的文件目录(SpringBoot默认获取静态资源和页面的设置可百度了解一下),web是自己创建的,名字可以改,之所以创建这个一个目录是将前后端分离,如果目录结构和我的这个不一样的,修改Vue的打包配置时需要对应上。
4)修改Vue中的打包配置
先了解一下文件的相对路径知识,web和static是同级目录。
对Vue的修改是上图目录中的web/config目录下的index.js,修改后代码如下:
'use strict' documentation. const path = require('path') module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: {}, host: 'localhost', // can be overwritten by process.env.HOST port: 9528, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: true, errorOverlay: true, notifyOnErrors: false, poll: false, useEslint: true, showEslintErrorsInOverlay: false, devtool: 'cheap-source-map', cssSourceMap: false }, // 整合打包主要是修改这个build build: { // Template for index.html // index为Vue的打包后的入口 index: path.resolve(__dirname, '../../resources/static/index.html'), // Paths assetsRoot: path.resolve(__dirname, '../../resources/static'), assetsSubDirectory: '', assetsPublicPath: '/', // 修改结束 productionSourceMap: false, devtool: 'source-map', productionGzip: false, productionGzipExtensions: ['js', 'css'], bundleAnalyzerReport: process.env.npm_config_report || false, generateAnalyzerReport: process.env.npm_config_generate_report || false } }
5)这样就可以
将打包好的Vue的东西直接放到static下了,原理很简单。
弄到别的路径就修改一下上面的打包路径。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。