const tag = require('./tag.js') const { writeFileSync, rmSync, ensureFileSync } = require('fs-extra') const { spawn } = require('node:child_process') const { globSync } = require('glob') const path = require('path') const fs = require('fs-extra') const slash = require('slash') const crossSpawn = require('cross-spawn') const { zip } = require('./ZipAFolder.js') const os = require('os') const chalk = require('chalk') const assetsUrl = 'https://lmes:gldt-ocw4NMSiDHD461ZoDvyK@gitlab.syc-cms.com:8443/lmes-plugin/web/assets.git' const baseDir = './node_modules/.cache/wwwroot' const baseBuildFile = './node_modules/.cache/widgets.json' const argvPath = './script/.argv' const hostPath = slash(path.resolve(process.cwd(), baseDir)) const hostZipPath = slash(path.resolve(process.cwd(), './wwwroot.zip')) let isSingleBuild = false let isDebugMode = false // 编译结束数量 let buildCount = 0 // 编译进程总数量 let buildSumCount = 0 let startTime = Date.now() removeHostPackage() buildWidgets() /** * 编译组件 */ function buildWidgets() { const isWin = process.platform === 'win32' const argv = process.argv || [] // 当debug模式下,将本地205环境下的图片地址映射到代码中,可以将.env环境进行设置VITE_STATIC_URL if (argv.includes('debug')) { isDebugMode = true argv.splice(argv.indexOf('debug'), 1) } const widgetName = argv[argv.length - 1] const widgetsPath = globSync(`./src/widgets/*/index.ts`) const widgetNames = widgetsPath.map((file) => { const parts = isWin ? path.resolve(file).split('\\') : path.resolve(file).split('/') return parts[parts.length - 2] }) try { fs.removeSync('./dist') } catch (error) { console.error('dist不存在,继续执行打包任务') } // 打包一个组件 if (widgetName && widgetNames.includes(widgetName)) { isSingleBuild = true writeFileSync(argvPath, widgetName) runBuild() } else { // 打包多组件,按CPU默认并行度打包 const buildWidgets = divideArray(widgetNames) const slashPath = slash(path.resolve(process.cwd(), baseBuildFile)) ensureFileSync(slashPath) writeFileSync(slashPath, JSON.stringify(buildWidgets, null, 2)) buildSumCount = 0 buildCount = 0 for (let index = 0; index < Object.keys(buildWidgets).length; index++) { const widgets = buildWidgets[index] if (widgets.length) { buildSumCount++ runBuild(index) } } console.log(buildWidgets) } } /** * 获取等分的组件数据 * @param {*} widgets * @param {*} cpus * @returns */ function divideArray(widgets) { // 当打包时,操作电脑可能会卡 const cpus = os.availableParallelism() let result = {} let dataPerKey = Math.floor(widgets.length / cpus) let remainingData = widgets.length for (let i = 0; i < cpus; i++) { let currentDataCount = Math.min(dataPerKey, remainingData) result[i] = widgets.splice(0, currentDataCount) remainingData -= currentDataCount } if (widgets.length) { widgets.forEach((widgetName, index) => { result[index].push(widgetName) }) } return result } /** * 运行编译 * @param {*} nodeIndex 设置打包组件起点 */ function runBuild(nodeIndex) { const cmdParams = ['run', 'build-lib'] cmdParams.push(isDebugMode ? 'development' : 'production') const run = spawn( process.platform === 'win32' ? 'npm.cmd' : 'npm', cmdParams, { stdio: 'inherit', shell: true, env: { // 编译组件索引映射 ...process.env, NODE_INDEX: nodeIndex, }, } ) run.on('close', async (code) => { if (code == 0 && isSingleBuild) rmSync(argvPath) // 添加打包hash buildCount++ await tag() if (!isSingleBuild) { if (buildCount >= buildSumCount) { console.log(chalk.green(`已经编译完所有组件,添加版本tag,请稍后...`)) console.log(chalk.green(`开始打包wwwroot.zip包`)) getHostPackage() } } }) } /** * 获取host包 zip包 * @param {*} */ function getHostPackage() { const resourcesPath = slash( path.resolve(process.cwd(), `${baseDir}/resources`) ) const widgetsPath = slash(path.resolve(process.cwd(), `${baseDir}/widgets`)) const currentDistPath = slash(path.resolve(process.cwd(), './dist')) const isResources = fs.existsSync(resourcesPath) const isWidgets = fs.existsSync(widgetsPath) if (!isResources) { fs.mkdirpSync(resourcesPath) } if (!isWidgets) { fs.mkdirpSync(widgetsPath) } const git = crossSpawn.sync('git', ['clone', assetsUrl, '-b', 'develop'], { stdio: 'inherit', cwd: resourcesPath, shell: true, }) if (git.status === 0) { fs.rmSync(slash(path.resolve(resourcesPath, './assets/.git')), { recursive: true, }) const dirs = globSync(slash(path.resolve(currentDistPath, './**/*.js'))) dirs.forEach((dir) => { const widgetName = slash(dir).replace(currentDistPath, '.') const widgetPath = slash(path.resolve(widgetsPath, widgetName)) fs.copySync(slash(dir), widgetPath) }) zipDir(hostPath, hostZipPath) .then(() => { console.log(chalk.green(`${hostZipPath} 压缩成功`)) fs.rmSync(hostPath, { recursive: true, }) console.log( chalk.green(`编译总时间: ${(Date.now() - startTime) / 1000}秒`) ) }) .catch((error) => { console.log(error) }) } } /** * 压缩zip包 * @param {*} dir * @param {*} zipPath * @returns */ function zipDir(dir, zipPath) { return new Promise(async (resolve, reject) => { try { await zip(slash(dir), slash(zipPath)) resolve() } catch (error) { reject(error) } }) } /** * 删除host包 * @param {*} */ function removeHostPackage() { if (fs.existsSync(hostPath)) { fs.rmSync(hostPath, { recursive: true, }) } if (fs.existsSync(hostZipPath)) { fs.rmSync(hostZipPath, { recursive: true, }) } }