schangxiang@126.com
2025-05-21 fa365d77dfa1d6619774a790e424e98dac849457
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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)
  })
}