const crossSpawn = require('cross-spawn') const slash = require('slash') const { writeFileSync, rmSync, ensureFileSync } = require('fs-extra') const { globSync } = require('glob') const path = require('path') const os = require('os') const baseBuildFile = './node_modules/.cache/widgets.json' let isSingleBuild = false const isWin = process.platform === 'win32' const argvPath = './script/.argv' const widgetName = process.argv[process.argv.length - 1] const widgetsPath = globSync(`./src/widgets/*/index.ts`) const getWidgetNames = widgetsPath.map((file) => { const parts = isWin ? path.resolve(file).split('\\') : path.resolve(file).split('/') return parts[parts.length - 2] }) if (getWidgetNames.includes(widgetName)) { isSingleBuild = true writeFileSync(argvPath, widgetName) } buildWidgets() function buildWidgets() { const isWin = process.platform === 'win32' const argv = process.argv || [] 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] }) // 打包一个组件 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() > 1 ? os.availableParallelism() - 1 : 1 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'] const run = crossSpawn( process.platform === 'win32' ? 'npm.cmd' : 'npm', cmdParams, { stdio: 'inherit', shell: true, env: { // 编译组件索引映射 ...process.env, NODE_INDEX: nodeIndex, }, } ) run.on('close', (code) => { if (code == 0 && isSingleBuild) rmSync(argvPath) }) }