niucloud/uni-app/scripts/generate-diy-registry.cjs
2026-07-14 17:02:06 +08:00

157 lines
5.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 扫描 DIY 微页面目录 → .build/diy-component-registry.json + .build/diy-component-registry.generated.ts
*/
const fs = require('fs')
const path = require('path')
const { ROOT, BUILD_DIR, listAddonKeys } = require('./addon-utils.cjs')
const { scanAllDiyComponents } = require('./diy-component-scan.cjs')
const OUT_JSON = path.join(BUILD_DIR, 'diy-component-registry.json')
const OUT_TS = path.join(BUILD_DIR, 'diy-component-registry.generated.ts')
// App 构建替换文件(消除 import.meta.glob避免 IIFE code-splitting 冲突)
const OUT_APP_REGISTRY = path.join(BUILD_DIR, 'diy-component-registry.dev.app.ts')
const OUT_APP_GLOBS_APP = path.join(BUILD_DIR, 'diy-component-globs.app.ts')
const OUT_APP_GLOBS_DEV = path.join(BUILD_DIR, 'diy-component-globs.dev.ts')
function generateDiyRegistry(options = {}) {
const addonKeys = options.addonKeys || listAddonKeys()
const { app, addon, all } = scanAllDiyComponents({ addonKeys })
const payload = {
version: 2,
generatedAt: new Date().toISOString(),
appCount: app.length,
addonCount: addon.length,
components: all
}
fs.mkdirSync(BUILD_DIR, { recursive: true })
fs.writeFileSync(OUT_JSON, JSON.stringify(payload, null, 2), 'utf-8')
const tsBody = `/* AUTO-GENERATED by generate-diy-registry.cjs — do not edit */
export interface DiyComponentMeta {
vueComponentName: string
scope: 'app' | 'addon'
folder: string
addonKey?: string
scrollBool?: boolean
formRef?: boolean
}
export const DIY_COMPONENT_REGISTRY: DiyComponentMeta[] = ${JSON.stringify(all, null, 4)} as DiyComponentMeta[]
export const DIY_COMPONENT_MAP: Record<string, DiyComponentMeta> = {
${all.map((e) => ` '${e.vueComponentName}': ${JSON.stringify(e)}`).join(',\n')}
}
`
fs.writeFileSync(OUT_TS, tsBody, 'utf-8')
console.log(
`[generate-diy-registry] ${all.length} components (app ${app.length}, addon ${addon.length}) -> ${path.relative(ROOT, OUT_JSON)}`
)
// ===== 生成 App 构建替换文件(用静态 import 替代 import.meta.glob =====
// 1) diy-component-registry.dev 替换 → 直接读取 generated 文件
const registryAppReplacement = `/* AUTO-GENERATED — App 构建替换,不使用 import.meta.glob */
import '../src/utils/pinia-preinit'
import type { DiyComponentMeta } from '../src/utils/diy-component-types'
import { DIY_COMPONENT_MAP } from './diy-component-registry.generated'
export function resolveDiyMeta(componentName: string): DiyComponentMeta | null {
if (!componentName) return null
return DIY_COMPONENT_MAP[componentName] ?? null
}
export function listDiyComponentNames() {
return Object.keys(DIY_COMPONENT_MAP)
}
`
fs.writeFileSync(OUT_APP_REGISTRY, registryAppReplacement, 'utf-8')
console.log(`[generate-diy-registry] App registry -> ${path.relative(ROOT, OUT_APP_REGISTRY)}`)
// 2) diy-component-globs.app 替换 → 静态 import 所有 app 级组件
const appCompImports = app
.map(
(c) =>
`import _${c.vueComponentName} from '../src/app/components/diy/${c.folder}/index.vue'`
)
.join('\n')
const appCompLoaders = app
.map(
(c) =>
` '../app/components/diy/${c.folder}/index.vue': () => Promise.resolve({ default: _${c.vueComponentName} })`
)
.join(',\n')
const appGlobsReplacement = `/* AUTO-GENERATED — App 构建替换,用静态 import 替代 import.meta.glob */
import '../src/utils/pinia-preinit'
import type { Component } from 'vue'
type DiyModuleLoader = () => Promise<{ default: Component }>
${appCompImports}
export const appDiyLoaders: Record<string, DiyModuleLoader> = {
${appCompLoaders}
}
export function appDiyGlobKey(folder: string) {
return \`../app/components/diy/\${folder}/index.vue\`
}
export function getAppDiyLoader(folder: string) {
return appDiyLoaders[appDiyGlobKey(folder)]
}
`
fs.writeFileSync(OUT_APP_GLOBS_APP, appGlobsReplacement, 'utf-8')
console.log(`[generate-diy-registry] App globs.app -> ${path.relative(ROOT, OUT_APP_GLOBS_APP)}`)
// 3) diy-component-globs.dev 替换 → 静态 import 所有 addon 级组件 + re-export app globs
const addonCompImports = addon
.map(
(c) =>
`import _${c.vueComponentName} from '../src/addon/${c.addonKey}/components/diy/${c.folder}/index.vue'`
)
.join('\n')
const addonCompLoaders = addon
.map(
(c) =>
` '../addon/${c.addonKey}/components/diy/${c.folder}/index.vue': () => Promise.resolve({ default: _${c.vueComponentName} })`
)
.join(',\n')
const devGlobsReplacement = `/* AUTO-GENERATED — App 构建替换,用静态 import 替代 import.meta.glob */
import '../src/utils/pinia-preinit'
import type { Component } from 'vue'
import { appDiyLoaders, getAppDiyLoader } from './diy-component-globs.app'
export { appDiyLoaders, getAppDiyLoader }
type DiyModuleLoader = () => Promise<{ default: Component }>
${addonCompImports}
export const addonDiyLoaders: Record<string, DiyModuleLoader> = {
${addonCompLoaders}
}
export function addonDiyGlobKey(addonKey: string, folder: string) {
return \`../addon/\${addonKey}/components/diy/\${folder}/index.vue\`
}
export function getAddonDiyLoader(addonKey: string, folder: string) {
return addonDiyLoaders[addonDiyGlobKey(addonKey, folder)]
}
`
fs.writeFileSync(OUT_APP_GLOBS_DEV, devGlobsReplacement, 'utf-8')
console.log(`[generate-diy-registry] App globs.dev -> ${path.relative(ROOT, OUT_APP_GLOBS_DEV)}`)
}
if (require.main === module) {
generateDiyRegistry()
}
module.exports = { generateDiyRegistry, OUT_JSON, OUT_TS, OUT_APP_REGISTRY, OUT_APP_GLOBS_APP, OUT_APP_GLOBS_DEV }