probe-t64-ssr.mjs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. // 探针:SSR 渲染 PanelBlocks(分页块)验证真实渲染行为。
  2. import { readFileSync } from 'node:fs'
  3. import { registerHooks } from 'node:module'
  4. import { parse, compileScript, compileTemplate } from '@vue/compiler-sfc'
  5. import { createSSRApp, h } from 'vue'
  6. import { renderToString } from '@vue/server-renderer'
  7. const root = new URL('../../../../../src/modules/cockpit/', import.meta.url)
  8. registerHooks({
  9. load(url, context, nextLoad) {
  10. if (url.endsWith('.json')) return { format: 'module', shortCircuit: true, source: `export default ${readFileSync(new URL(url), 'utf8')}` }
  11. if (url.endsWith('.vue')) {
  12. const { descriptor } = parse(readFileSync(new URL(url), 'utf8'), { filename: new URL(url).pathname })
  13. const script = compileScript(descriptor, { id: 'probe', genDefaultAs: '__sfc__' })
  14. const template = compileTemplate({
  15. source: descriptor.template.content, filename: new URL(url).pathname,
  16. id: 'probe', ssr: true, compilerOptions: { bindingMetadata: script.bindings },
  17. })
  18. return { format: 'module', shortCircuit: true, source: `${script.content}\n${template.code}\n__sfc__.ssrRender = ssrRender; export default __sfc__;` }
  19. }
  20. return nextLoad(url, context)
  21. },
  22. })
  23. const { default: PanelBlocks } = await import(new URL('components/PanelBlocks.vue', root))
  24. const { operationPanel, managementPanel, toOperatingInformation, toManagementInformation } = await import(new URL('domain/infrastructurePanels.js', root))
  25. const { section } = await import(new URL('domain/sectionState.js', root))
  26. const payload = JSON.parse(readFileSync(new URL('../t51/oi-unfiltered.json', import.meta.url), 'utf8')).data
  27. const data = toOperatingInformation(payload)
  28. const view = operationPanel(data, section('success', { data, loaded: true }), { scope: 'all' })
  29. const html = await renderToString(createSSRApp({ render: () => h(PanelBlocks, { view }) }))
  30. console.log('cards:', (html.match(/data-item="/g) || []).length)
  31. console.log('pager:', /data-pager/.test(html), 'state:', (html.match(/data-page-state>([^<]*)</) || [])[1])
  32. console.log('title 运行指标:', /运行指标/.test(html), 'old title gone:', !/指标占位/.test(html))
  33. console.log('sourceNote rendered(hidden):', /设施实体|逐条生成/.test(html))
  34. const m = toManagementInformation({ totals: { facilityCount: 9, equipmentCount: 9 }, districtIndustry: Array.from({ length: 9 }, (_, i) => ({ district: i % 3, industry: 'GAS', facilityCount: 1, equipmentCount: 1 })) })
  35. const mv = managementPanel(m, section('success', { data: m, loaded: true }))
  36. const mh = await renderToString(createSSRApp({ render: () => h(PanelBlocks, { view: mv }) }))
  37. console.log('mgmt cards:', (mh.match(/data-item="/g) || []).length, 'mgmt pager:', /data-pager/.test(mh))