219 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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 => {
 | ||
|     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}/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();
 | ||
| 
 |