const fsExtra = require('fs-extra') const path = require('path') const chalk = require('chalk') const fs = require('fs') const {exec} = require("child_process"); /** * 将函数封装成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 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)) })) } /** * 生成对应的main入口js文件 */ const generateMain = project => { let cores, apps const getCores = new Promise(resolve => { 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(project + "加载核心库配置..") 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, "/")}) } }).then(() => { chalkTag.done(project + '核心库打包完毕') resolve() }) } else { chalkTag.done(project + '核心库无打包') resolve() } }) }) const getApps = new Promise(resolve => { const appLib = path.join(__dirname, project.toString(), 'apps.import.json') fsExtra.readJson(appLib, (err, data) => { chalkTag.info(project + '加载业务应用配置...') 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, "/")}) } }).then(() => { chalkTag.done(project + '业务应用打包完毕') resolve() }) } else { chalkTag.done(project + '业务应用无打包') resolve() } }) }) return Promise.all([getCores, getApps]).then(() => new Promise(resolve => { if (project == 'dvui') { return resolve() } chalkTag.info(project + '正在生成打包文件...') let bin = path.join(__dirname, project.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) else chalkTag.done(project + '生成打包文件') resolve() }) })).then(() => { 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(project + '正在压缩文件中...') exec(cmd, { cwd: path.join(__dirname, '..') }, (err) => { if (!err) { chalkTag.done(project + '打包成功!') } else { chalkTag.error(err) } }) }) }) } const start = () => { //询问打包哪个项目 init().then(choices => { return Promise.all(choices.map(prj => generateMain(prj))).then(() => { chalkTag.done('完成生成打包文件') }) }) } start();