Files
dvcp_v2_webapp/project/build.js
2022-03-25 14:36:46 +08:00

222 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fsExtra = require('fs-extra')
const path = require('path')
const {exec} = require('child_process')
const inquirer = require("inquirer");
const chalk = require('chalk')
const fs = require('fs')
/**
* 将函数封装成promise
*/
const promisify = fn => {
return function () {
let args = arguments;
return new Promise(function (resolve, reject) {
[].push.call(args, function (err, result) {
if (err) {
console.log(err)
reject(err);
} else {
resolve(result);
}
});
fn.apply(null, args);
});
}
}
const readdir = promisify(fs.readdir)
const stat = promisify(fs.stat)
/**
* 封装打印工具
*/
const {log} = console
const chalkTag = {
info: msg => log([chalk.bgBlue.black(' INFO '), msg].join(' ')),
done: msg => log([chalk.bgGreen.black(' DONE '), msg].join(' ')),
warn: msg => log([chalk.bgYellow.black(' WARN '), msg].join(' ')),
error: msg => log([chalk.bgRed.black(' ERROR '), msg].join(' ')),
}
const start = () => {
let cores, apps
//询问打包哪个项目
init().then(async choices => {
return await inquirer.prompt([{
name: "PROJECT",
type: 'list',
message: "要打包发布哪一个项目?",
choices
}])
}).then(res => new Promise(resolve => {
const {PROJECT} = res
let install = path.join(__dirname, PROJECT, 'index.js')
fsExtra.ensureFile(install)
const coreLib = path.join(__dirname, PROJECT, 'core.import.json')
fsExtra.readJson(coreLib, (err, data) => {
chalkTag.info("加载核心库配置..")
cores = []
if (data) {
findApp('core/apps', file => {
let fileName = file.replace(/.*\\(.+)\.vue/g, '$1')
if (Object.keys(data).includes(fileName)) {
cores.push({name: fileName, component: file.replace(/\\/g, "/")})
log(">>>正在打包核心库...%s", fileName)
}
}).then(() => {
chalkTag.done('核心库打包完毕')
resolve(PROJECT)
})
} else {
chalkTag.done('核心库无打包')
resolve(PROJECT)
}
})
})).then(prj => new Promise(resolve => {
const appLib = path.join(__dirname, prj.toString(), 'apps.import.json')
fsExtra.readJson(appLib, (err, data) => {
chalkTag.info('加载业务应用配置...')
apps = []
let appDir = "packages"
if (data) {
findApp(appDir, file => {
let fileName = file.replace(/.*\\(.+)\.vue/g, '$1')
if (Object.keys(data).includes(fileName)) {
apps.push({name: fileName, component: file.replace(/\\/g, "/")})
log(">>>正在打包业务应用...%s", fileName)
}
}).then(() => {
chalkTag.done('业务应用打包完毕')
resolve(prj)
})
} else {
inquirer.prompt([{
name: "CONFIRM",
type: 'confirm',
message: "未读取到业务应用配置文件,是否要打包整个packages?",
}]).then(res => {
if (res.CONFIRM) {
findApp(appDir, file => {
if (/.*\\(App[^\\]+)\.vue/g.test(file)) {
let fileName = file.replace(/.*\\(App[^\\]+)\.vue/g, '$1')
apps.push({name: fileName, component: file.replace(/\\/g, "/")})
log(">>>正在打包业务应用...%s", fileName)
}
}).then(() => {
chalkTag.done('业务应用打包完毕')
resolve(prj)
})
} else {
chalkTag.done('业务应用无打包')
resolve(prj)
}
})
}
})
})).then(prj => new Promise(resolve => {
if (prj == 'dvui') {
return resolve(prj)
}
chalkTag.info('正在生成打包文件...')
let bin = path.join(__dirname, prj.toString(), 'index.js'),
coreApps = cores.map(e => `{name:'${e.name}',component:require('../../${e.component}').default}`),
bizApps = apps.map(e => `{name:'${e.name}',component:require('../../${e.component}').default}`),
comps = [...coreApps, ...bizApps],
content = `
const apps = [${comps.toString()}]
const install = function (Vue) {
if (install.installed) return Promise.resolve()
else{
let contexts = require.context('.', true, /(\\/.+)\\/App[^\\/]+\\.vue$/)
if (contexts) {
contexts.keys().map(e => {
if (contexts(e).default) {
let mod = apps.find(a=>a.name==contexts(e).default.name)
if(mod){
mod.component = contexts(e).default
}else{
apps.push({name:contexts(e).default.name,component:contexts(e).default})
}
}
})
}
apps.map(e=>{
Vue.component(e.name,e.component)
})
}
}
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
// 导出的对象必须具有 install才能被 Vue.use() 方法安装
install
}
`
fsExtra.outputFile(bin, content, err => {
if (err) {
chalkTag.error(err)
reject()
} else chalkTag.done('生成打包文件')
resolve(prj)
})
})).then(project => new Promise((resolve, reject) => {
fsExtra.readJson(path.join(__dirname, project.toString(), 'package.json'), (err, json) => {
let cmd = `vue-cli-service build --target lib --dest project/${project}/dist project/${project}/${project == 'dvui' ? 'entries' : 'index'}.js --name ${json.name}`
chalkTag.info('正在压缩文件中...')
exec(cmd, {
cwd: path.join(__dirname, '..')
}, (err, stdout) => {
log(stdout);
if (!err) {
chalkTag.done('打包成功!')
resolve(project)
} else {
chalkTag.error(err)
reject()
}
})
})
})).then(project => {
chalkTag.info('正在发布中...')
let cmd = `cd ${project}&npm unpublish --force&npm publish`
exec(cmd, {
cwd: path.join(__dirname, '.')
}, (err, stdout) => {
log(stdout);
if (!err) {
chalkTag.done('发布成功!')
} else chalkTag.error(err)
})
})
}
/**
* 遍历应用的方法
*/
const findApp = (dir, cb) => {
return readdir(dir).then(apps => {
return Promise.all(apps.map(e => {
let cPath = path.join(dir, e)
return stat(cPath).then(state => {
if (state.isDirectory()) {
return findApp(cPath, cb)
} else if (state.isFile()) {
cb && cb(cPath)
}
})
}) || [])
})
}
/**
* 初始化打包配置文件
*/
const init = () => {
chalkTag.info('开始运行项目打包工具...')
return new Promise(resolve => fs.readdir('./project', (err, files) => {
resolve(files.filter(e => e.indexOf('.') < 0))
}))
}
start();