mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-08-01 20:15:49 +00:00
248 lines
8.5 KiB
JavaScript
248 lines
8.5 KiB
JavaScript
/**
|
||
* 打包单个插件小程序源码 → dist/mp-addons/{key}/
|
||
* 含 addon/{key}/...、common/、manifest.json(subPackages 等合并信息)
|
||
*/
|
||
const fs = require('fs')
|
||
const path = require('path')
|
||
const {
|
||
ROOT,
|
||
PAGES_JSON,
|
||
BUILD_DIR,
|
||
MP_OUT_BUILD,
|
||
MP_CORE_DIR,
|
||
MP_ADDONS_DIR,
|
||
MP_LOCK_PATH,
|
||
makeBuildId,
|
||
runUniMpBuild,
|
||
readJson,
|
||
writeJson,
|
||
readAppJson,
|
||
rmDir,
|
||
copyDir,
|
||
getSubPackageRootsForKey,
|
||
parsePagesJson,
|
||
collectCommonManifest,
|
||
stripAddonSubpackagesExcept,
|
||
getAppSubPackages,
|
||
getAddonPackageDir,
|
||
installMergeScriptToFramework,
|
||
copyMpRelativeFiles,
|
||
readMpSharedBridgeMeta,
|
||
installMpSharedBridgePage,
|
||
removeMpSharedBridgePage,
|
||
packageSharedAddonComponents,
|
||
collectMainComponentDirs,
|
||
packageMainComponents,
|
||
packageAddonDiyBridge
|
||
} = require('./mp-utils.cjs')
|
||
const { buildAddonDiyRegistryMap } = require('./mp-diy-bridge-merge.cjs')
|
||
const { scanAllDiyComponents } = require('./diy-component-scan.cjs')
|
||
const { scanSubPackageRequires } = require('./scan-mp-requires.cjs')
|
||
|
||
const PAGES_BACKUP = path.join(BUILD_DIR, 'pages.full.backup.json')
|
||
|
||
function swapPagesJson(key, enable, rawBackup) {
|
||
const pagesAddon = path.join(BUILD_DIR, `pages.addon.${key}.json`)
|
||
if (enable) {
|
||
if (!fs.existsSync(pagesAddon)) {
|
||
console.error(`[build-mp-addon] missing ${path.relative(ROOT, pagesAddon)}`)
|
||
process.exit(1)
|
||
}
|
||
// 保存原始内容(保留注释)
|
||
rawBackup = fs.readFileSync(PAGES_JSON, 'utf-8')
|
||
fs.copyFileSync(pagesAddon, PAGES_JSON)
|
||
console.log(`[build-mp-addon] swapped pages.json -> pages.addon.${key}.json`)
|
||
return rawBackup
|
||
} else if (rawBackup) {
|
||
fs.writeFileSync(PAGES_JSON, rawBackup, 'utf-8')
|
||
console.log('[build-mp-addon] restored pages.json (with comments)')
|
||
}
|
||
}
|
||
|
||
function packageAddonBuild(key, buildDir, buildId) {
|
||
const pagesJson = parsePagesJson()
|
||
const roots = getSubPackageRootsForKey(key, pagesJson)
|
||
const appJson = readAppJson(buildDir)
|
||
const subPackages = getAppSubPackages(appJson).filter((s) => roots.includes(s.root))
|
||
|
||
const dest = getAddonPackageDir(key)
|
||
rmDir(dest)
|
||
fs.mkdirSync(dest, { recursive: true })
|
||
|
||
for (const root of roots) {
|
||
const src = path.join(buildDir, root)
|
||
if (!fs.existsSync(src)) {
|
||
console.error(`[build-mp-addon] missing ${root}`)
|
||
process.exit(1)
|
||
}
|
||
copyDir(src, path.join(dest, root))
|
||
}
|
||
|
||
const commonSrc = path.join(buildDir, 'common')
|
||
if (fs.existsSync(commonSrc)) {
|
||
copyDir(commonSrc, path.join(dest, 'common'))
|
||
}
|
||
|
||
const nodeModulesSrc = path.join(buildDir, 'node-modules')
|
||
if (fs.existsSync(nodeModulesSrc)) {
|
||
copyDir(nodeModulesSrc, path.join(dest, 'node-modules'))
|
||
}
|
||
|
||
const scan = scanSubPackageRequires(buildDir, roots, key)
|
||
const depFiles = copyMpRelativeFiles(buildDir, dest, scan.requirePaths, roots)
|
||
if (depFiles) {
|
||
console.log(`[build-mp-addon] packaged ${depFiles} main-package dep file(s)`)
|
||
}
|
||
|
||
const bridgeMeta = readMpSharedBridgeMeta(key)
|
||
const sharedCount = packageSharedAddonComponents(buildDir, dest, bridgeMeta.sharedComponents)
|
||
if (sharedCount) {
|
||
console.log(`[build-mp-addon] packaged ${sharedCount} shared addon/components`)
|
||
}
|
||
|
||
const mainComponentDirs = collectMainComponentDirs(buildDir, roots, bridgeMeta)
|
||
const mainComponentCount = packageMainComponents(buildDir, dest, mainComponentDirs)
|
||
if (mainComponentCount) {
|
||
console.log(`[build-mp-addon] packaged ${mainComponentCount} main component dir(s)`)
|
||
}
|
||
|
||
const diyBridgeCount = packageAddonDiyBridge(key, buildDir, dest)
|
||
if (diyBridgeCount) {
|
||
console.log(
|
||
`[build-mp-addon] packaged diy-dynamic-bridge-${key} (${diyBridgeCount} components)`
|
||
)
|
||
}
|
||
|
||
const diyRegistry = buildAddonDiyRegistryMap(scanAllDiyComponents, key)
|
||
|
||
const manifest = {
|
||
key,
|
||
kind: 'mp-addon-package',
|
||
roots,
|
||
buildId,
|
||
gitCommit: null,
|
||
time: new Date().toISOString(),
|
||
subPackages,
|
||
sharedComponents: bridgeMeta.sharedComponents,
|
||
mainComponents: bridgeMeta.mainComponents,
|
||
mainComponentDirs,
|
||
deps: scan,
|
||
commonManifest: collectCommonManifest(buildDir),
|
||
diyBridge: {
|
||
key,
|
||
componentDir: `components/diy-dynamic-bridge-${key}`,
|
||
componentCount: diyBridgeCount || 0,
|
||
registry: diyRegistry
|
||
}
|
||
}
|
||
writeJson(path.join(dest, 'manifest.json'), manifest)
|
||
console.log(`[build-mp-addon] packaged -> ${path.relative(ROOT, dest)}/`)
|
||
return manifest
|
||
}
|
||
|
||
function main() {
|
||
const key = process.argv[2]
|
||
if (!key) {
|
||
console.error('Usage: node build-mp-addon.cjs <addon-key>')
|
||
process.exit(1)
|
||
}
|
||
|
||
const buildId = makeBuildId(`mp-addon-${key}`)
|
||
|
||
// 自动生成 pages.core.json(确保所有插件的分包信息最新)
|
||
const genSplitResult = require('child_process').spawnSync(
|
||
'node',
|
||
[path.join(__dirname, 'generate-split-pages.cjs')],
|
||
{ cwd: ROOT, stdio: 'inherit', shell: process.platform === 'win32' }
|
||
)
|
||
if (genSplitResult.status !== 0) {
|
||
console.error('[build-mp-addon] generate-split-pages failed')
|
||
process.exit(genSplitResult.status || 1)
|
||
}
|
||
|
||
spawnSyncGenerate(key)
|
||
require('./generate-diy-registry.cjs').generateDiyRegistry({ addonKeys: [key] })
|
||
require('./generate-diy-dynamic-bridge-mp.cjs').generateDiyDynamicBridgeMp({
|
||
target: 'addon',
|
||
addonKey: key
|
||
})
|
||
|
||
const bridgeInstalled = installMpSharedBridgePage(key)
|
||
const pagesBackup = swapPagesJson(key, true)
|
||
|
||
// 额外安全措施:把备份也写入磁盘,即使 finally 未执行也能手动恢复
|
||
fs.writeFileSync(path.join(BUILD_DIR, 'pages.last.backup.json'), pagesBackup, 'utf-8')
|
||
|
||
process.env.MP_ADDON_BRIDGE_KEY = key
|
||
let buildOk = false
|
||
let exitCode = 1
|
||
try {
|
||
console.log(`[build-mp-addon] building "${key}" ...`)
|
||
const code = runUniMpBuild()
|
||
if (code !== 0) {
|
||
console.error('[build-mp-addon] FAILED')
|
||
exitCode = code
|
||
return
|
||
}
|
||
if (!fs.existsSync(MP_OUT_BUILD)) {
|
||
console.error('[build-mp-addon] missing output:', MP_OUT_BUILD)
|
||
exitCode = 1
|
||
return
|
||
}
|
||
stripAddonSubpackagesExcept(MP_OUT_BUILD, [key])
|
||
const manifest = packageAddonBuild(key, MP_OUT_BUILD, buildId)
|
||
manifest.gitCommit = require('./mp-utils.cjs').getGitCommit()
|
||
writeJson(path.join(getAddonPackageDir(key), 'manifest.json'), manifest)
|
||
|
||
const lock = fs.existsSync(MP_LOCK_PATH) ? readJson(MP_LOCK_PATH) : {}
|
||
lock.addons = lock.addons || {}
|
||
lock.addons[key] = { buildId, dir: path.relative(ROOT, getAddonPackageDir(key)) }
|
||
writeJson(MP_LOCK_PATH, lock)
|
||
|
||
if (fs.existsSync(MP_CORE_DIR)) {
|
||
installMergeScriptToFramework(MP_CORE_DIR)
|
||
const frameworkAddonDir = path.join(MP_CORE_DIR, 'mp-addons', key)
|
||
rmDir(frameworkAddonDir)
|
||
copyDir(getAddonPackageDir(key), frameworkAddonDir)
|
||
console.log(`[build-mp-addon] synced -> ${path.relative(ROOT, frameworkAddonDir)}/`)
|
||
}
|
||
|
||
console.log(`[build-mp-addon] OK (${buildId})`)
|
||
console.log(`[build-mp-addon] 插件包 -> ${path.relative(ROOT, getAddonPackageDir(key))}/`)
|
||
console.log('[build-mp-addon] 合并:cd dist/build/mp-core && node merge-mp-addon.cjs')
|
||
buildOk = true
|
||
exitCode = 0
|
||
} catch (e) {
|
||
console.error('[build-mp-addon] unexpected error:', e.message || e)
|
||
exitCode = 1
|
||
} finally {
|
||
delete process.env.MP_ADDON_BRIDGE_KEY
|
||
swapPagesJson(key, false, pagesBackup)
|
||
// 恢复成功后删除磁盘备份
|
||
try { fs.unlinkSync(path.join(BUILD_DIR, 'pages.last.backup.json')) } catch {}
|
||
if (bridgeInstalled) {
|
||
removeMpSharedBridgePage()
|
||
}
|
||
if (buildOk) {
|
||
require('./cleanup-diy-dynamic-bridge-src.cjs').cleanupAddonDiyBridgeSrc({ keys: [key] })
|
||
}
|
||
}
|
||
|
||
if (exitCode !== 0) {
|
||
process.exit(exitCode)
|
||
}
|
||
}
|
||
|
||
function spawnSyncGenerate(key) {
|
||
const result = require('child_process').spawnSync(
|
||
'node',
|
||
[path.join(__dirname, 'generate-mp-addon-pages.cjs'), key],
|
||
{ cwd: ROOT, stdio: 'inherit', shell: process.platform === 'win32' }
|
||
)
|
||
if (result.status !== 0) {
|
||
process.exit(result.status || 1)
|
||
}
|
||
}
|
||
|
||
main()
|