/** * 组装 H5 分构建最终产物 → dist/build/h5/ */ const fs = require('fs') const path = require('path') const { spawnSync } = require('child_process') const { ROOT, listAddonKeys } = require('./addon-utils.cjs') const { IMPORT_MAP, SHARED_BUILD_ORDER } = require('./shared-external.cjs') const { fixDir } = require('./wap-locale-import-utils.cjs') const { applyRouterBase } = require('./apply-router-base.cjs') const { patchAddonDir } = require('./patch-addon-uni-h5.cjs') const { patchVueJsFile } = require('./uni-feature-defines.cjs') const { stripAddonStyleImport } = require('./inject-addon-style-import.cjs') const { injectChunkScopedCss } = require('./inject-addon-chunk-scoped-css.cjs') const { injectChunkWindiCss } = require('./inject-addon-chunk-windi.cjs') const { patchAddonDir: patchAddonLocaleLeak } = require('./patch-addon-locale-leak.cjs') const { patchAddonDir: patchAddonDiyLeak } = require('./patch-addon-diy-leak.cjs') const { patchCoreH5Dir: patchCoreLocaleExternal } = require('./patch-core-locale-external.cjs') const { mergeIntoWapLocale } = require('./merge-addon-locales-into-wap-locale.cjs') const CORE_DIR = path.join(ROOT, 'dist', '.core', 'h5') const ADDONS_STAGING = path.join(ROOT, 'dist', '.addons') const SHARED_DIR = path.join(ROOT, 'dist', '.shared') const OUT_DIR = path.join(ROOT, 'dist', 'build', 'h5') const REPORT_PATH = path.join(ROOT, 'build-report.json') function rmDir(dir) { if (!fs.existsSync(dir)) return fs.rmSync(dir, { recursive: true, force: true, maxRetries: 8, retryDelay: 300 }) } function copyDir(src, dest) { fs.mkdirSync(dest, { recursive: true }) for (const name of fs.readdirSync(src)) { const s = path.join(src, name) const d = path.join(dest, name) if (fs.statSync(s).isDirectory()) copyDir(s, d) else fs.copyFileSync(s, d) } } function copyTree(src, dest) { fs.mkdirSync(path.dirname(dest), { recursive: true }) fs.cpSync(src, dest, { recursive: true, force: true }) } function cleanCoreAssetsOutput() { const outAssets = path.join(OUT_DIR, 'assets') if (!fs.existsSync(outAssets)) { fs.mkdirSync(outAssets, { recursive: true }) return null } const addonsSrc = path.join(outAssets, 'addons') const addonsTmp = path.join(OUT_DIR, '.addons_staging') if (fs.existsSync(addonsTmp)) rmDir(addonsTmp) if (fs.existsSync(addonsSrc)) { fs.renameSync(addonsSrc, addonsTmp) } const staleAssets = path.join(OUT_DIR, `.assets_stale_${Date.now()}`) try { fs.renameSync(outAssets, staleAssets) } catch { rmDir(outAssets) return null } fs.mkdirSync(outAssets, { recursive: true }) if (fs.existsSync(addonsTmp)) { fs.renameSync(addonsTmp, path.join(outAssets, 'addons')) } return staleAssets } function cleanupAssembleArtifacts(staleAssets) { if (staleAssets) rmDir(staleAssets) if (!fs.existsSync(OUT_DIR)) return for (const name of fs.readdirSync(OUT_DIR)) { if (name.startsWith('.assets_stale_')) { rmDir(path.join(OUT_DIR, name)) } } const addonsStaging = path.join(OUT_DIR, '.addons_staging') if (fs.existsSync(addonsStaging)) rmDir(addonsStaging) } function mergeCoreOutput() { fs.mkdirSync(OUT_DIR, { recursive: true }) for (const name of fs.readdirSync(CORE_DIR)) { if (name === 'assets') continue const src = path.join(CORE_DIR, name) const dest = path.join(OUT_DIR, name) if (fs.statSync(src).isDirectory()) copyTree(src, dest) else fs.copyFileSync(src, dest) console.log(`[assemble-wap] core ${name}`) } const coreAssets = path.join(CORE_DIR, 'assets') const outAssets = path.join(OUT_DIR, 'assets') if (!fs.existsSync(coreAssets)) return fs.mkdirSync(outAssets, { recursive: true }) for (const name of fs.readdirSync(coreAssets)) { if (name === 'addons') continue const src = path.join(coreAssets, name) const dest = path.join(outAssets, name) if (fs.statSync(src).isDirectory()) copyDir(src, dest) else fs.copyFileSync(src, dest) } } function copyLocale(key, destAddonDir) { const localeSrc = path.join(ROOT, 'src', 'addon', key, 'locale') if (!fs.existsSync(localeSrc)) return copyDir(localeSrc, path.join(destAddonDir, 'locale')) } function copyAppLocale() { const localeSrc = path.join(ROOT, 'src', 'app', 'locale') if (!fs.existsSync(localeSrc)) return copyDir(localeSrc, path.join(OUT_DIR, 'assets', 'locale', 'app')) } function writeAddonManifest(key, destAddonDir) { const manifest = { key, version: '1.0.0', sharedVersion: 'wap-core-1.0.0', entry: './index.js', localeBase: './locale/' } fs.writeFileSync(path.join(destAddonDir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf-8') } function fixIndexHtml() { const fn = path.join(OUT_DIR, 'index.html') if (!fs.existsSync(fn)) return let text = fs.readFileSync(fn, 'utf-8') text = text.replaceAll('./assets/', '/wap/assets/') fs.writeFileSync(fn, text, 'utf-8') } function injectImportMap() { const fn = path.join(OUT_DIR, 'index.html') if (!fs.existsSync(fn)) return let text = fs.readFileSync(fn, 'utf-8') const script = `` if (text.includes('type="importmap"')) { text = text.replace(/