Commit b2bb6f72 authored by 莫坚培's avatar 莫坚培

feat: 先增加配置文件

parent e4f53ab5
node_modules
dist
*.tar
*.tar.gz
*.zip
\ No newline at end of file
/*
* @Author: 莫靓仔
* @description: node执行该文件,修改全局配置
* @Date: 2021-09-02 09:40:29
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 11:09:45
*/
let fs = require('fs')
let chalk = require('chalk')
let apiMap = {
dev: 'https://apidev.sycdev.com',
test: 'https://api.sycdev.com',
pre: 'https://apipre.sycdev.com',
prod: 'https://slmapi.shengyc.com',
tx: 'https://apitx.shengyc.com',
newDev: 'https://apidev-alpha.sycdev.com',
newTest: 'https://api-alpha.sycdev.com'
}
let urlMap = {
dev: 'https://slmdev.sycdev.com',
test: 'https://slm.sycdev.com',
pre: 'https://slmpre.sycdev.com',
prod: 'https://slm.shengyc.com',
tx: '',
newDev: '',
newTest: ''
}
let textMap = {
test: '测试环境',
dev: '开发环境',
pre: '预发布环境',
prod: '正式环境',
newDev: '新开发环境',
newTest: '新测试环境'
}
let domainMap = {
test: 'sycdev.com',
dev: 'sycdev.com',
pre: 'sycdev.com',
prod: 'shengyc.com',
newDev: 'sycdev.com',
newTest: 'sycdev.com'
}
function changeEnv() {
let env_ = process.argv[2]
let res = {
apiUrl: apiMap[env_],
baseUrl: urlMap[env_],
domain: domainMap[env_],
name: textMap[env_]
}
fs.writeFile('./config/config.json', JSON.stringify(res), function (err) {
if (err) {
throw err
}
console.log(chalk.green(`成功切换到【${textMap[env_]}】!`))
})
}
changeEnv()
{"apiUrl":"https://apidev.sycdev.com","baseUrl":"https://slmdev.sycdev.com","domain":"sycdev.com","name":"开发环境"}
\ No newline at end of file
/*
* @Author: 莫靓仔
* @description: 文件描述
* @Date: 2021-09-02 11:13:07
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 20:00:51
*/
const os = require('os')
const ssh2 = require('ssh2')
const sshconfig = require('./scp/envload.js')
// const ora = require('ora')
const chalk = require('chalk')
console.log(chalk.blue('正在发布到【' + sshconfig.name + '】服务器...'))
// var ProgressBar = require('progress')
// var bar = new ProgressBar(':bar :current/:total', { total: 10 });
// var timer = setInterval(function () {
// bar.tick();
// if (bar.complete) {
// clearInterval(timer);
// } else if (bar.curr === 5) {
// bar.interrupt('this message appears above the progress bar\ncurrent progress is ' + bar.curr + '/' + bar.total);
// }
// }, 1000);
// const spinner = ora('正在发布到' + sshconfig.name + '服务器...')
let conn = new ssh2.Client()
let url = 'sycloud'
if (sshconfig.name === '新开发环境' || sshconfig.name === '新测试环境') {
url = 'sycloudv2'
}
// 上传
// spinner.start()
//针对MACOS 系统做处理调用本地scp命令
if (sshconfig.localScp == 1) {
macosScp().then(
function (data) {
console.log(chalk.green('\n', 'sshpass成功', '\n'))
connect(remoteCommand)
},
function (reason) {
console.log(chalk.red('\n', 'sshpass失败,失败原因:', reason, '\n'))
error()
}
)
} else {
connect(uploadStart)
}
function macosScp() {
let p = new Promise(function (resolve, reject) {
const process = require('child_process')
const cmd = `sshpass -p ${sshconfig.password} scp ./ci_scp/tmp/dist.tar.gz ${sshconfig.username}@${sshconfig.host}:/opt/w/${url}/tmp/${sshconfig.app}_dist.tar.gz`
process.exec(cmd, function (error, stdout, stderr) {
let b = true
if (error) {
b = false
reject(error)
}
if (stdout) {
b = false
resolve(stdout)
}
if (b) resolve('scp success!')
})
})
return p
}
// 上传操作
function connect(callback) {
conn.on('ready', () => {
callback()
}).connect({
host: sshconfig.host,
port: sshconfig.port,
username: sshconfig.username,
password: sshconfig.password
})
}
function uploadStart() {
conn.sftp((err, sftp) => {
if (err) {
error()
throw err
}
let targetPackage = './config/tmp/dist.tar.gz'
let serverPackage = `/opt/w/${url}/tmp/${sshconfig.app}_dist.tar.gz`
if (os.type() == 'Windows_NT') {
targetPackage = './config/tmp/dist.zip'
serverPackage = `/opt/w/${url}/tmp/${sshconfig.app}_dist.zip`
}
sftp.fastPut(targetPackage, serverPackage, {}, (err, result) => {
if (err) {
error()
throw err
}
//上传完成后开始解压
remoteCommand()
})
})
}
// 解压部署操作
function remoteCommand() {
conn.shell((err, stream) => {
if (err) {
error()
throw err
}
let scpCommand = `
cd /opt/w/${url}/
rm -rf ${sshconfig.app}_backup.tar.gz
tar -zcf ${sshconfig.app}_backup.tar.gz ${sshconfig.app}/
rm -rf ${sshconfig.app}
mv /opt/w/${url}/tmp/${sshconfig.app}_dist.tar.gz dist.tar.gz
tar -zxf dist.tar.gz
rm -rf dist.tar.gz
exit
`
if (os.type() == 'Windows_NT') {
scpCommand = `
cd /opt/w/${url}/
rm -rf ${sshconfig.app}_backup.tar.gz
tar -zcf ${sshconfig.app}_backup.tar.gz ${sshconfig.app}/
rm -rf ${sshconfig.app}
mv /opt/w/${url}/tmp/${sshconfig.app}_dist.zip dist.zip
unzip dist.zip
rm -rf dist.zip
exit
`
}
stream
.end(scpCommand)
.on('data', data => {
//不输出日志
//console.log(chalk.green(data.toString()))
})
.on('close', () => {
conn.end()
// spinner.stop()
console.log(chalk.green('Success! 成功发布到【' + sshconfig.name + '【服务器! \n'))
})
})
}
function error() {
// spinner.stop()
conn.end()
console.log(chalk.red('发布失败.\n'))
}
/*
* @Description: 这是***页面(组件)
* @Date: 2021-03-08 17:34:17
* @Author: 米虫
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 11:16:07
*/
const app = 'bi'
module.exports = {
'develop':{
app: app,
name: '开发环境',
host: '116.63.67.122',
port: 22,
username: 'vuedeployer'
},
'test':{
app: app,
name: '测试环境',
host: '122.9.119.75',
port: 22,
username: 'vuedeployer'
},
//待配置
'pre-release':{
app: app,
name: '预发布环境',
host: '139.159.226.120',
port: 22,
username: 'vuedeployer'
},
'new-develop':{
app: app,
name: '新开发环境',
host: '116.63.67.122',
port: 22,
username: 'vuedeployer'
},
'new-test':{
app: app,
name: '新测试环境',
host: '122.9.119.75',
port: 22,
username: 'vuedeployer'
},
}
\ No newline at end of file
/*
* @Description: 这是***页面(组件)
* @Date: 2021-03-12 21:42:35
* @Author: 米虫
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 16:35:38
* @description: 文件描述
*/
const envScpConfig = require('./env')
const os = require('os')
const fs = require('fs')
const env = process.env
//默认IOS LINUX
let homePath = env.HOME
//windows
if (os.type() == 'Windows_NT') homePath = env.USERPROFILE
const ciphertextPath = homePath + '/syc-vue-deploy/' + env.NODE_ENV + '.txt'
const ciphertext = fs.readFileSync(ciphertextPath, 'utf8')
let localScp = 0
try {
const localScpPath = homePath + '/syc-vue-deploy/localScp.txt'
localScp = fs.readFileSync(localScpPath, 'utf8')
} catch (error) {
localScp = 0
}
if (!ciphertext) {
throw new Error('获取不到密码!请联系管理员授权!')
}
envScpConfig[env.NODE_ENV]['password'] = ciphertext
envScpConfig[env.NODE_ENV]['localScp'] = localScp
module.exports = envScpConfig[env.NODE_ENV]
<!--
* @Author: 莫靓仔
* @description:
* @Date: 2021-09-03 18:29:01
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 18:29:02
-->
这只是一个占位文件,没有实际作用。
\ No newline at end of file
/*
* @Author: 莫靓仔
* @description: 文件描述
* @Date: 2021-09-02 11:27:54
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 19:54:30
*/
const path = require('path')
const fs = require('fs')
const os = require('os')
const del = require('del')
const JsZip = require('jszip')
const zip = new JsZip()
const chalk = require('chalk')
const compressing = require('compressing')
// 要压缩的文件夹目录
const sourceDir = path.join(__dirname, '../dist')
// 生成压缩包的目录
const targetDir = path.join(__dirname, './tmp/dist.zip')
function starTarGz() {
console.log(chalk.blue('正在压缩...'))
// 流写法
// function handleError(err) {
// console.log(err)
// }
// const tarStream = new compressing.tar.Stream()
// tarStream.addEntry('dist/bi')
// tarStream.on('error', handleError).pipe(fs.createWriteStream('./config/tmp/dist.tar')).on('error', handleError)
// new compressing.tar.FileStream({ source: path.resolve('../dist/bi') })
// .on('error', handleError)
// .pipe(fs.createWriteStream('./config/tmp/dist.tar'))
// .on('error', handleError)
// // It's a transform stream, so you can pipe to it
// fs.createReadStream('dist/bi')
// .on('error', handleError)
// .pipe(new compressing.tar.FileStream())
// .on('error', handleError)
// .pipe(fs.createWriteStream('./config/tmp/dist.tar'))
// .on('error', handleError)
// promise写法
compressing.tar
.compressDir('dist/bi', './config/tmp/dist.tar')
.then(res => {
console.log(chalk.green('tar压缩完成!'))
compressing.gzip
.compressFile('./config/tmp/dist.tar', './config/tmp/dist.tar.gz')
.then(() => {
console.log(chalk.green('gz压缩完成!'))
del.sync(path.join(__dirname, './tmp/dist.tar'))
})
.catch(err => {
console.log(chalk.red('gz压缩失败!'), err)
})
})
.catch(err => {
console.log(chalk.red('tar压缩失败!'))
console.log(err)
})
}
// 读取目录及文件
function readDir(zipObj, nowPath, nowFolder) {
// 读取目录中的所有文件及文件夹
let files = fs.readdirSync(nowPath)
files.forEach(fileName => {
// 遍历检测目录中的文件
let filePath = `${nowPath}/${fileName}`
let file = fs.statSync(filePath)
if (file.isDirectory()) {
// 如果是文件夹,继续读取
let path = `${nowPath}/${fileName}`
// 压缩对象中生成该目录,replace是为了去掉前面的系统目录
let dirList = zip.folder(path.replace(`${sourceDir}`, ''))
// let dirList = zip.folder(filePath.replace(`${__dirname}/dist/`, ''))
// 重新检索目录文件
readDir(dirList, filePath)
} else {
// 如果是文件则压缩
zipObj.file(fileName, fs.readFileSync(filePath))
}
})
}
// 开始压缩文件
function startZIP() {
console.log(chalk.blue('正在压缩...'))
// 先清掉原来的
del.sync(targetDir)
// 读取文件,往zip中塞东西
readDir(zip, sourceDir, '')
zip.generateAsync({
type: 'nodebuffer',
compression: 'DEFLATE',
compressionOptions: {
level: 9
}
})
.then(content => {
fs.writeFile(targetDir, content, 'utf-8', err => {
if (err) {
throw err
}
console.log(chalk.green('压缩完成!'))
})
})
.catch(err => {
console.log(err)
})
}
if (os.type() == 'Windows_NT') {
// zip压缩
startZIP()
} else {
// 使用tar.gz格式(Linux系统识别),zip为windows的格式
// https://github.com/npm/node-tar
// https://www.npmjs.com/package/compressing
starTarGz()
}
/*
* @Author: 莫靓仔
* @description: 使用gulp压缩文件
* @Date: 2021-08-26 10:25:20
* @LastEditors: 莫靓仔
* @LastEditTime: 2021-09-03 16:47:23
*/
const OUTPUT = './dist'
const fs = require('fs')
const os = require('os')
const del = require('del')
const path = require('path')
const allPath = path.resolve('./')
const distPath = path.resolve(OUTPUT)
const gulp = require('gulp')
const uglify = require('gulp-uglify')
const babel = require('gulp-babel')
const minifyCSS = require('gulp-minify-css')
const imagemin = require('gulp-imagemin')
const htmlmin = require('gulp-htmlmin')
// const through = require('through2')
// const browserify = require('browserify')
// const webpack = require('webpack-stream')
// const named = require('vinyl-named')
// const buffer = require('vinyl-buffer')
// const stream = require('vinyl-source-stream')
// 忽略的目录
const ignoreList = [
path.resolve(OUTPUT),
path.resolve('./node_modules'),
path.resolve('./config/tmp'),
path.resolve('./.vscode'),
path.resolve('./.git'),
path.resolve('./package.json'),
path.resolve('./package-lock.json'),
path.resolve('./yarn.lock'),
path.resolve('./yarn-lock.lock')
]
// 忽略函数这些关键字的文件
const ignoreKeyword = ['jquery', 'min', 'layui', 'laydate', 'echarts.js', 'node_modules', 'vscode', 'moment', 'ecStat']
// 获取所有文件路径
const getSrcFile = () => {
let fileClass = {
js: [],
css: [],
html: [],
image: [],
others: []
}
/**
* 获取所有文件的
* @param filePath 文件夹路径
* @param status 是否需要打包
*/
function getAllFile(filePath, status) {
if (ignoreList.includes(filePath)) {
return
}
let files = fs.readdirSync(filePath)
files.forEach(file => {
// 读取所有的文件夹
let fileDir = path.join(filePath, file)
let flag = ignoreKeyword.find(item => fileDir.indexOf(item) > -1)
let fileStat = fs.statSync(fileDir)
if (fileStat.isDirectory()) {
// 如果是文件夹 递归获取下面的文件
// 忽略目录的不打包
if (ignoreList.includes(fileDir)) {
getAllFile(fileDir, false)
} else {
getAllFile(fileDir, status)
}
} else if (fileStat.isFile()) {
if (status && !flag) {
// 需要打包的
if (/\.js$/.test(file)) {
// fileClass.js.push(fileDir)
// 因存在es6语法转义之后与commonjs规范冲突的问题尚未解决,暂不压缩js
fileClass.others.push(fileDir)
} else if (/\.css$/.test(file)) {
fileClass.css.push(fileDir)
} else if (/\.html$/.test(file)) {
fileClass.html.push(fileDir)
} else if (/\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$/.test(file)) {
fileClass.image.push(fileDir)
} else {
// 其他的直接复制,不处理
fileClass.others.push(fileDir)
}
} else {
fileClass.others.push(fileDir)
}
}
})
}
getAllFile(allPath, true)
return fileClass
}
const { js, css, html, image, others } = getSrcFile()
// 计算每个文件的输出文职
const getOutputPath = filePath => {
// 区分windows和mac
let url = os.type() == 'Windows_NT' ? '\\' : '/'
let res = `${distPath}${allPath.substring(allPath.lastIndexOf(url))}${filePath.split(allPath)[1]}`
return res.slice(0, res.lastIndexOf(url))
}
// 编译,打包压缩js
function jsGulp(cb) {
js.forEach(file => {
jsTask(file)
})
cb()
}
function jsTask(file) {
let destPath = getOutputPath(file)
return (
gulp
.src(file)
.pipe(
babel({
presets: [
[
'@babel/preset-env',
{
useBuiltIns: false
}
]
],
plugins: [
[
'@babel/plugin-transform-runtime',
{
absoluteRuntime: false,
corejs: false,
helpers: false,
regenerator: true,
useESModules: false
}
]
]
})
)
// .pipe(
// browserify({
// entries: file,
// debug: true
// })
// .bundle()
// .on('error', function (error) {
// })
// .pipe(stream(file))
// .pipe(buffer())
// )
// .pipe(named())
// .pipe(
// webpack({
// mode: 'production',
// module: {
// rules: [
// {
// test: /\.js$/,
// use: [
// {
// loader: 'babel-loader',
// options: {
// presets: ['@babel/env'],
// plugins: ['@babel/plugin-transform-runtime']
// }
// }
// ],
// exclude: /node_modules/
// }
// ]
// }
// })
// )
.pipe(uglify())
.pipe(gulp.dest(destPath))
)
}
// 压缩css
function cssGulp(cb) {
css.forEach(file => {
cssTask(file)
})
cb()
}
function cssTask(file) {
let destPath = getOutputPath(file)
return gulp.src(file).pipe(minifyCSS()).pipe(gulp.dest(destPath))
}
// 压缩图片
function imageGulp(cb) {
image.forEach(file => {
imageTask(file)
})
cb()
}
function imageTask(file) {
let destPath = getOutputPath(file)
return (
gulp
.src(file)
.pipe(
imagemin({
progressive: true
})
)
// .on('error', err => {
// imageFlag = false
// })
.pipe(gulp.dest(destPath))
)
// .on('end', () => {
// })
}
// 压缩html
function htmlGulp(cb) {
html.forEach(file => {
htmlTask(file)
})
cb()
}
function htmlTask(file) {
const htmlOptions = {
keepClosingSlash: true,
caseSensitive: true,
removeComments: true, //清除HTML注释
collapseWhitespace: true, //压缩HTML
removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input />
removeScriptTypeAttributes: true, //删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css"
minifyCSS: true,
minifyJS: true,
continueOnParseError: true
}
let destPath = getOutputPath(file)
return gulp.src(file).pipe(htmlmin(htmlOptions)).pipe(gulp.dest(destPath))
}
// 其他文件不作处理,直接复制
function copyGulp(cb) {
others.forEach(file => {
copyTask(file)
})
cb()
}
function copyTask(file) {
let destPath = getOutputPath(file)
// console.log('destPath', destPath)
return gulp.src(file).pipe(gulp.dest(destPath))
}
// 清除原来的压缩包
function cleanGulp(cb) {
del.sync(OUTPUT)
cb()
}
// series 串行执行所有任务
// parallel 并行执行所有任务
// 先删除dist文件夹,在执行打包任务(所有打包任务一起执行)
exports.default = gulp.series(cleanGulp, gulp.parallel(jsGulp, cssGulp, htmlGulp, imageGulp, copyGulp))
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment