/** * 生成小程序用 DIY bridge(静态 v-if,禁止 ) * * target: * app -> diy-dynamic-bridge-app(框架 app 微页面) * addon -> diy-dynamic-bridge-{key}(单插件微页面,供 zip 合并) * router-> diy-dynamic-bridge.router(开发期 vue router,mp-core 用原生模板) */ const fs = require('fs') const path = require('path') const { ROOT, BUILD_DIR } = require('./addon-utils.cjs') const { scanAllDiyComponents } = require('./diy-component-scan.cjs') const REGISTRY_JSON = path.join(BUILD_DIR, 'diy-component-registry.json') function importPath(entry) { if (entry.scope === 'app') { return `@/app/components/diy/${entry.folder}/index.vue` } return `@/addon/${entry.addonKey}/components/diy/${entry.folder}/index.vue` } function resolveOutputPath(options = {}) { if (options.target === 'app' || options.appOnly) { return path.join(ROOT, 'src/components/diy-dynamic-bridge-app/diy-dynamic-bridge-app.mp.vue') } if (options.target === 'addon' && options.addonKey) { const key = options.addonKey return path.join(ROOT, `src/components/diy-dynamic-bridge-${key}/diy-dynamic-bridge-${key}.mp.vue`) } if (options.target === 'router') { return path.join(ROOT, 'src/components/diy-dynamic-bridge/diy-dynamic-bridge.router.mp.vue') } return path.join(ROOT, 'src/components/diy-dynamic-bridge/diy-dynamic-bridge.mp.vue') } function loadComponents(options = {}) { if (options.target === 'app' || options.appOnly) { return scanAllDiyComponents(options).app } if (options.target === 'addon' && options.addonKey) { return scanAllDiyComponents({ addonKeys: [options.addonKey] }).addon } if (options.target === 'router') { return [] } if (options.addonKeys && options.addonKeys.length) { const { app, addon } = scanAllDiyComponents({ addonKeys: options.addonKeys }) return [...app, ...addon].sort((a, b) => a.vueComponentName.localeCompare(b.vueComponentName)) } if (fs.existsSync(REGISTRY_JSON)) { const data = JSON.parse(fs.readFileSync(REGISTRY_JSON, 'utf-8')) if (Array.isArray(data.components) && data.components.length) { return data.components } } return scanAllDiyComponents(options).all } function buildBridgeVue(components) { const imports = components .map((entry) => `import ${entry.vueComponentName} from '${importPath(entry)}'`) .join('\n') const blocks = components .map( (entry) => ` <${entry.vueComponentName} v-if="componentName === '${entry.vueComponentName}'" :ref="setInnerRef" :component="component" :global="global" :index="index" :scrollBool="scrollBool" @update:componentIsShow="emit('update:componentIsShow', $event)" @loadingFn="emit('loadingFn', $event)" />` ) .join('\n') return ` ` } function buildRouterVue() { return ` ` } function ensureBridgeShells(options = {}) { const appVue = path.join(ROOT, 'src/components/diy-dynamic-bridge-app/diy-dynamic-bridge-app.vue') fs.mkdirSync(path.dirname(appVue), { recursive: true }) if (!fs.existsSync(appVue)) { fs.writeFileSync( appVue, `\n\n\n`, 'utf-8' ) } if (options.addonKey) { const key = options.addonKey const addonVue = path.join(ROOT, `src/components/diy-dynamic-bridge-${key}/diy-dynamic-bridge-${key}.vue`) fs.mkdirSync(path.dirname(addonVue), { recursive: true }) fs.writeFileSync( addonVue, `\n\n\n`, 'utf-8' ) } } function describeScope(options, count) { if (options.target === 'app' || options.appOnly) return `app-only (${count})` if (options.target === 'addon' && options.addonKey) return `addon/${options.addonKey} (${count})` if (options.target === 'router') return 'router' if (options.addonKeys?.length) return `app + ${options.addonKeys.join(', ')} (${count})` return `full registry (${count})` } function generateDiyDynamicBridgeMp(options = {}) { ensureBridgeShells(options) const outPath = resolveOutputPath(options) const vue = options.target === 'router' ? buildRouterVue() : buildBridgeVue(loadComponents(options)) fs.mkdirSync(path.dirname(outPath), { recursive: true }) fs.writeFileSync(outPath, vue, 'utf-8') const count = options.target === 'router' ? 0 : loadComponents(options).length console.log( `[generate-diy-dynamic-bridge-mp] ${describeScope(options, count)} -> ${path.relative(ROOT, outPath)}` ) return outPath } module.exports = { generateDiyDynamicBridgeMp, resolveOutputPath, ensureBridgeShells, OUT_VUE: path.join(ROOT, 'src/components/diy-dynamic-bridge/diy-dynamic-bridge.mp.vue') } if (require.main === module) { const { generateDiyRegistry } = require('./generate-diy-registry.cjs') generateDiyRegistry() generateDiyDynamicBridgeMp() }