公司项目管理平台为前后端分离框架,前端工程系基于vue-admin框架实现。每次jenkins编译出包时需针对vue前端工程执行以下单独的shell编译打包流程,详细如下:
#0. 代理连接外网,nodejs需要拉js包
export http_proxy=http://172.30.28.35:3128
export https_proxy=http://172.30.28.35:3128
export NODE_HOME=/home/devops/node-v10.13.0-linux-x64
export PATH=$NODE_HOME/bin:$PATH
#1. xxx-admin-frontent前端工程构建
# 1.1 xxx-admin-fronted构建
source ~/.bash_profile
cd $WORKSPACE/xxx-admin/xxx-admin-frontend/target/
npm cache clean --force
npm config set registry https://registry.npm.taobao.org/
npm install
npm install webpack
npm run test
# 将编译生成的dist文件夹打成tar包并scp到目标机器tmp目录
cd $WORKSPACE/xxx-admin/xxx-admin-frontend/target/dist/
tar czvf xxx-admin-frontent.tar . --warning=no-file-changed
cd $WORKSPACE/xxx-admin/xxx-admin-frontend/target/
scp ./xxx-admin-frontend.tar [email protected]:/home/xxx/tmp
现希望直接基于maven插件实现前后端工程的混合编译打包,省略上述配置。
该方案实现以下目标:
具体实现如下:
前端工程xxx-admin-frontent工程pom.xml配置文件增加如下配置:
<build>
<finalName>xxx-admin-frontendfinalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>exec-maven-pluginartifactId>
<version>1.6.0version>
<configuration>
<skip>${skipDeploy}skip>
configuration>
<executions>
<execution>
<id>exec-npm-installid>
<phase>generate-resourcesphase>
<goals>
<goal>execgoal>
goals>
<configuration>
<executable>npmexecutable>
<arguments>
<argument>installargument>
arguments>
<workingDirectory>${basedir}/vueworkingDirectory>
configuration>
execution>
<execution>
<id>exec-npm-run-buildid>
<phase>generate-resourcesphase>
<goals>
<goal>execgoal>
goals>
<configuration>
<executable>npmexecutable>
<arguments>
<argument>runargument>
<arguments>${package.environment}arguments>
arguments>
<workingDirectory>${basedir}/vueworkingDirectory>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-assembly-pluginartifactId>
<version>3.3.0version>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
<configuration>
<skipAssembly>${skipDeploy}skipAssembly>
<appendAssemblyId>falseappendAssemblyId>
<finalName>xxx-admin-frontendfinalName>
<descriptors>
<descriptor>assembly.xmldescriptor>
descriptors>
configuration>
execution>
executions>
plugin>
plugins>
build>
<profiles>
<profile>
<id>localid>
<properties>
<package.environment>localpackage.environment>
properties>
profile>
<profile>
<id>testid>
<properties>
<package.environment>testpackage.environment>
properties>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
profile>
<profile>
<id>uatid>
<properties>
<package.environment>uatpackage.environment>
properties>
profile>
<profile>
<id>prodid>
<properties>
<package.environment>build:prodpackage.environment>
properties>
profile>
profiles>
其中assembly.xml配置内容如下:
<assembly>
<id>xxx-admin-frontendid>
<formats>
<format>tarformat>
formats>
<includeBaseDirectory>falseincludeBaseDirectory>
<fileSets>
<fileSet>
<directory>${basedir}/vue/distdirectory>
<includes>
<include>**/*include>
includes>
<outputDirectory>/outputDirectory>
fileSet>
fileSets>
assembly>
其中pom.xml中支持profile环境参数的配置,对应的package.json中npm执行参数配置如下:
"scripts": {
"init": "webpack --progress --config build/webpack.local.config.js",
"lint": "eslint --fix --ext .js,.vue src",
"local": "webpack-dev-server --host 0.0.0.0 --content-base ./ --open --inline --hot --compress --config build/webpack.local.config.js",
"test": "webpack --progress --hide-modules --config build/webpack.test.config.js",
"uat": "webpack --progress --hide-modules --config build/webpack.uat.config.js",
"build:prod": "webpack --progress --hide-modules --config build/webpack.prod.config.js"
}
maven构建的参数如下:
-s /home/devops/.m2/settingsnewglobal.xml -Dmaven.test.skip=true clean install -P test -DskipDeploy=false
-DskipDeploy=true 即指定jenkins编译出包时跳过前端vue工程的编译打包环节。
注意:以上配置生效的前提是jenkins服务器已经安装有node.js以及npm环境,当前jenkins服务器安装的node.js版本为node 12.18.3,方案一生效的前提是jenkins服务器已经安装有node.js以及npm环境,如需打包时安装node.js以及npm环境,可参考方案二。
方案二实现以下目标:
<build>
<finalName>xxx-admin-frontendfinalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>exec-maven-pluginartifactId>
<version>1.6.0version>
<configuration>
<skip>${skipDeploy}skip>
configuration>
<executions>
<execution>
<id>exec-npm-installid>
<phase>generate-resourcesphase>
<goals>
<goal>execgoal>
goals>
<configuration>
<executable>npmexecutable>
<arguments>
<argument>installargument>
arguments>
<workingDirectory>${basedir}/vueworkingDirectory>
configuration>
execution>
<execution>
<id>exec-npm-run-buildid>
<phase>generate-resourcesphase>
<goals>
<goal>execgoal>
goals>
<configuration>
<executable>npmexecutable>
<arguments>
<argument>runargument>
<arguments>${package.environment}arguments>
arguments>
<workingDirectory>${basedir}/vueworkingDirectory>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-assembly-pluginartifactId>
<version>3.3.0version>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
<configuration>
<skipAssembly>${skipDeploy}skipAssembly>
<appendAssemblyId>falseappendAssemblyId>
<finalName>xxx-admin-frontendfinalName>
<descriptors>
<descriptor>assembly.xmldescriptor>
descriptors>
configuration>
execution>
executions>
plugin>
plugins>
build>
<profiles>
<profile>
<id>localid>
<properties>
<package.environment>localpackage.environment>
properties>
profile>
<profile>
<id>testid>
<properties>
<package.environment>testpackage.environment>
properties>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
profile>
<profile>
<id>uatid>
<properties>
<package.environment>uatpackage.environment>
properties>
profile>
<profile>
<id>prodid>
<properties>
<package.environment>build:prodpackage.environment>
properties>
profile>
profiles>
其中pom.xml中支持profile环境参数的配置,对应的package.json中npm执行参数配置如下:
"scripts": {
"init": "webpack --progress --config build/webpack.local.config.js",
"lint": "eslint --fix --ext .js,.vue src",
"local": "webpack-dev-server --host 0.0.0.0 --content-base ./ --open --inline --hot --compress --config build/webpack.local.config.js",
"test": "webpack --progress --hide-modules --config build/webpack.test.config.js",
"uat": "webpack --progress --hide-modules --config build/webpack.uat.config.js",
"build:prod": "webpack --progress --hide-modules --config build/webpack.prod.config.js"
}
aseemble.xml配置如下:
<assembly>
<id>xxx-admin-frontendid>
<formats>
<format>tarformat>
formats>
<includeBaseDirectory>falseincludeBaseDirectory>
<fileSets>
<fileSet>
<directory>${basedir}/vue/distdirectory>
<includes>
<include>**/*include>
includes>
<outputDirectory>/outputDirectory>
fileSet>
fileSets>
assembly>
cleanFiles.js内容如下:
const fs = require('fs')
const p = require('path')
const nodeModulesPath = p.join(__dirname, '../../node_modules')
const lockJsonPath = p.join(__dirname, '../../package-lock.json')
if (fs.existsSync(nodeModulesPath)) {
const fileUtil = require('./fileUtil')
fileUtil.deleteFolderByRimraf(nodeModulesPath)
console.log('删除 node_modules 成功!')
fileUtil.deleteFile(lockJsonPath)
console.log('删除 package-lock.json 成功!')
}
fileUtil.js内容如下:
const fs = require('fs')
const rimraf = require('rimraf');
/**
* 删除文件夹
* @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)
}
}
}
/**
* 使用 rimraf 删除文件夹
* @param path
*/
function deleteFolderByRimraf (path) {
rimraf(path, (err) => {
if (err) {
console.log(err)
}
})
}
/**
* 删除文件
* @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,
deleteFolderByRimraf,
deleteFile,
copyFolder
}