SpringBoot+vue2联合部署,混合部署
前端工程和后端工程目前是都是相对独立性的模式进行开发的。
打包机 只拥有maven,没有nodejs
软件工程场景:
- 前后端工程在同一个父工程下面,作为一个子工程存在,各自独立开发。
- 前端工程作为一个独立的目录存在于后端代码中,前端目录的根目录(例如front)与后端工程的src目录同级。--本文的例子采用的是这种模式。
打包发布场景:
- 不将前端单独打包发布至nginx服务器中。
- 服务器只能部署一个war包。--本文的例子采用的是这种模式。
当满足上述场景的时候,可以采用以下打包部署方案

- 优先将前端构建打包,将前端构建出的内容,copy至后端SpringBoot工程的webapp目录下。
- 在通过maven打包后端,这样就可以将前端资源打保进war中了。
实现
主要是在前端处理。
在前端工程中增加脚本,脚本调用入口在package.json文件中。通过node调用文件copy的脚本。
            
            
              json
              
              
            
          
          {
  ...
  ...
  "scripts": {
    "build-copy": "vue-cli-service build && node src/utils/fileCopy.js"
  },
  ...
  ...
}fileCopy.js
先删除目标路径(后端工程中的前端文件的路径)下的内容,在将新生成的前端文件copy过去。
            
            
              js
              
              
            
          
          const fileUtil = require('./fileUtil')
// 目标文件夹
const staticDirectory = '../src/main/webapp/'
// 删除
fileUtil.deleteFolder(staticDirectory + "static")
fileUtil.deleteFile(staticDirectory + "index.html")
// 拷贝
fileUtil.copyFolder('./server/dist', staticDirectory)
console.log('文件拷贝成功!')fileUtil.js
借助fs模块进行文件操作。
            
            
              js
              
              
            
          
          const fs = require('fs')
/**
 * 删除该路径下所有的内容
 * @param path
 */
function deleteFolder(path) {
  let files = []
  if (fs.existsSync(path)) {
    if (fs.statSync(path).isDirectory()) {
      files = fs.readdirSync(path)
      files.forEach((file) => {
        const curPath = path + '/' + file
        if (fs.statSync(curPath).isDirectory()) {
          deleteFolder(curPath)
        } else {
          fs.unlinkSync(curPath)
        }
      })
      fs.rmdirSync(path)
    } else {
      fs.unlinkSync(path)
    }
  }
}
/**
 * 删除文件
 * @param path
 */
function deleteFile(path) {
  if (fs.existsSync(path)) {
    if (fs.statSync(path).isDirectory()) {
      deleteFolder(path)
    } else {
      fs.unlinkSync(path)
    }
  }
}
/**
 * 复制路径下的内容到指定目录
 * @param from
 * @param to
 */
function copyFolder(from, to) {
  let files = []
  // 文件是否存在 如果不存在则创建
  if (fs.existsSync(to)) {
    files = fs.readdirSync(from)
    files.forEach((file) => {
      const targetPath = from + '/' + file
      const toPath = to + '/' + file
      // 复制文件夹
      if (fs.statSync(targetPath).isDirectory()) {
        copyFolder(targetPath, toPath)
      } else {
        // 拷贝文件
        fs.copyFileSync(targetPath, toPath)
      }
    })
  } else {
    fs.mkdirSync(to)
    copyFolder(from, to)
  }
}
module.exports = {
  deleteFolder,
  deleteFile,
  copyFolder
}问题:
- 在管理代码上需要进行手动执行前端打包,容易忘记。
- 对本地开发环境需要同时支持特定版本的nodejs和npm。
打包机同时拥有maven和nodejs。
如果打包机同时拥有maven和nodejs。可以借助maven插件frontend-maven-plugin进行一步打包。
            
            
              xml
              
              
            
          
          <groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>若需要使用这个插件,需要将软件工程,调整为,后端工程和前端工程平级,同属于一个父工程的子工程下面。在父工程的pom文件中,定义模块时,需要将前端模块顺序放在后端之前,这样做,主要是为了解决前后端的打包顺序问题。
            
            
              java
              
              
            
          
          <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  ...
  ...
    <modules>
        <module>frontend</module>
        <module>server</module>
    </modules>
</project>前端工程中需要增加一个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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <version>1.8.0</version>
        <executions>
          <!-- 检查是否安装node npm -->
          <execution>
            <id>install node and npm</id>
            <goals>
              <goal>install-node-and-npm</goal>
            </goals>
            <phase>generate-resources</phase>
          </execution>
          <!-- 执行脚本,删除node_modules和package-lock.json -->
          <execution>
            <id>npm run clean</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <arguments>run clean</arguments>
            </configuration>
          </execution>
          <!-- npm install -->
          <execution>
            <id>npm install</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <arguments>install --registry=https://registry.npm.taobao.org</arguments>
            </configuration>
          </execution>
          <!-- build 之后复制文件到 src/main/resource/static 下 -->
          <execution>
            <id>npm run build</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <phase>generate-resources</phase>
            <configuration>
              <arguments>run build-copy</arguments>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <nodeVersion>v10.24.1</nodeVersion>
          <npmVersion>6.14.12</npmVersion>
          <!-- node安装路径 -->
          <installDirectory>${settings.localRepository}</installDirectory>
          <!-- 前端代码路径 -->
          <workingDirectory>${basedir}</workingDirectory>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>通过调用父工程的mvn clean install即可。
问题:
- 
首次安装 nodejs和npm会很慢。 
- 
打包机需要可以访问淘宝镜像。或者搭建本地镜像,将对应的node和npm安装包放进去才可以。