@uniweb/build 0.11.8 → 0.11.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/vite-foundation-plugin.js +138 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/build",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.9",
|
|
4
4
|
"description": "Build tooling for the Uniweb Component Web Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"@uniweb/theming": "0.1.3"
|
|
59
59
|
},
|
|
60
60
|
"optionalDependencies": {
|
|
61
|
-
"@uniweb/
|
|
61
|
+
"@uniweb/schemas": "0.2.1",
|
|
62
62
|
"@uniweb/runtime": "0.8.9",
|
|
63
|
-
"@uniweb/
|
|
63
|
+
"@uniweb/content-reader": "1.1.9"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* - Processing preview images for presets
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { writeFile, mkdir } from 'node:fs/promises'
|
|
10
|
+
import { writeFile, mkdir, readFile } from 'node:fs/promises'
|
|
11
|
+
import { existsSync } from 'node:fs'
|
|
11
12
|
import { join, resolve } from 'node:path'
|
|
12
13
|
import { buildSchema } from './schema.js'
|
|
13
14
|
import { generateEntryPoint, shouldRegenerateForFile } from './generate-entry.js'
|
|
@@ -41,6 +42,119 @@ async function buildSchemaWithPreviews(srcDir, outDir, isProduction, sectionPath
|
|
|
41
42
|
*/
|
|
42
43
|
let _buildingSSRBundle = false
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Emit dist/runtime-pin.json declaring the @uniweb/runtime version this
|
|
47
|
+
* foundation was built against. Read by the edge isolate (under the
|
|
48
|
+
* Strategy S split-bundle path) to decide which runtime/{ver}/ssr.js to
|
|
49
|
+
* side-load from R2. See kb/platform/plans/edge-ssr-bundling-strategy.md
|
|
50
|
+
* and kb/platform/operations/release-workflow.md.
|
|
51
|
+
*
|
|
52
|
+
* Reads the resolved version from the foundation's node_modules/@uniweb/
|
|
53
|
+
* runtime/package.json so the pin reflects what was actually linked at
|
|
54
|
+
* build time, not what the foundation's own package.json range happens
|
|
55
|
+
* to allow.
|
|
56
|
+
*
|
|
57
|
+
* Silently no-ops when @uniweb/runtime isn't resolvable (e.g., the
|
|
58
|
+
* foundation depends on the runtime via a workspace alias that puts it
|
|
59
|
+
* elsewhere). The edge resolver treats the absence of a pin as the
|
|
60
|
+
* legacy single-bundle path, so omitting the pin is harmless during the
|
|
61
|
+
* dual-mode window.
|
|
62
|
+
*
|
|
63
|
+
* Optional foundation-author override: a `uniweb.runtimePolicy` field
|
|
64
|
+
* in the foundation's own package.json gets recorded alongside the
|
|
65
|
+
* runtime version so the registry's semver resolver can apply it.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} outDir - dist/ directory to write to.
|
|
68
|
+
* @param {string} projectRoot - foundation project root (where package.json lives).
|
|
69
|
+
*/
|
|
70
|
+
async function emitRuntimePin(outDir, projectRoot) {
|
|
71
|
+
// Resolve @uniweb/runtime via two strategies, in order:
|
|
72
|
+
// 1. createRequire from this plugin's location (catches the runtime
|
|
73
|
+
// pulled in transitively through @uniweb/build, @uniweb/core, etc.).
|
|
74
|
+
// 2. Walk up node_modules from the project root (catches the case
|
|
75
|
+
// where the foundation depends on runtime directly).
|
|
76
|
+
// The first covers the common case (foundations don't typically depend
|
|
77
|
+
// on runtime directly — it's the host environment, not a foundation
|
|
78
|
+
// import); the second is a safety net.
|
|
79
|
+
let runtimePkgPath = null
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
// Resolve via an exported subpath, not 'package.json' directly —
|
|
83
|
+
// @uniweb/runtime's `exports` map doesn't include package.json, so
|
|
84
|
+
// require.resolve on it throws ERR_PACKAGE_PATH_NOT_EXPORTED.
|
|
85
|
+
// Walking back from the resolved subpath finds the package root.
|
|
86
|
+
const { createRequire } = await import('node:module')
|
|
87
|
+
const { dirname: pathDirname } = await import('node:path')
|
|
88
|
+
const pluginRequire = createRequire(import.meta.url)
|
|
89
|
+
const ssrEntry = pluginRequire.resolve('@uniweb/runtime/ssr')
|
|
90
|
+
let dir = pathDirname(ssrEntry)
|
|
91
|
+
for (let i = 0; i < 5; i++) {
|
|
92
|
+
const candidate = join(dir, 'package.json')
|
|
93
|
+
if (existsSync(candidate)) {
|
|
94
|
+
const pkg = JSON.parse(await readFile(candidate, 'utf-8'))
|
|
95
|
+
if (pkg.name === '@uniweb/runtime') {
|
|
96
|
+
runtimePkgPath = candidate
|
|
97
|
+
break
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const parent = resolve(dir, '..')
|
|
101
|
+
if (parent === dir) break
|
|
102
|
+
dir = parent
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Fall through to the walk-up search.
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!runtimePkgPath) {
|
|
109
|
+
let dir = projectRoot
|
|
110
|
+
for (let i = 0; i < 10; i++) {
|
|
111
|
+
const candidate = join(dir, 'node_modules', '@uniweb', 'runtime', 'package.json')
|
|
112
|
+
if (existsSync(candidate)) {
|
|
113
|
+
runtimePkgPath = candidate
|
|
114
|
+
break
|
|
115
|
+
}
|
|
116
|
+
const parent = resolve(dir, '..')
|
|
117
|
+
if (parent === dir) break
|
|
118
|
+
dir = parent
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!runtimePkgPath) {
|
|
123
|
+
// No runtime resolvable. Skip emission — edge will treat as legacy.
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let runtimeVersion
|
|
128
|
+
try {
|
|
129
|
+
const pkg = JSON.parse(await readFile(runtimePkgPath, 'utf-8'))
|
|
130
|
+
runtimeVersion = pkg.version
|
|
131
|
+
} catch {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
if (!runtimeVersion) return
|
|
135
|
+
|
|
136
|
+
// Read foundation's own package.json for an optional runtimePolicy
|
|
137
|
+
// field. Default policy (auto-patch) lives at the registry layer; we
|
|
138
|
+
// only record the foundation's override if explicitly set.
|
|
139
|
+
let policy = null
|
|
140
|
+
try {
|
|
141
|
+
const foundationPkgPath = join(projectRoot, 'package.json')
|
|
142
|
+
if (existsSync(foundationPkgPath)) {
|
|
143
|
+
const foundationPkg = JSON.parse(await readFile(foundationPkgPath, 'utf-8'))
|
|
144
|
+
policy = foundationPkg?.uniweb?.runtimePolicy ?? null
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// Foundation package.json malformed; skip policy. Pin still emits.
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const pin = { runtime: runtimeVersion }
|
|
151
|
+
if (policy) pin.policy = policy
|
|
152
|
+
|
|
153
|
+
const pinPath = join(outDir, 'runtime-pin.json')
|
|
154
|
+
await writeFile(pinPath, JSON.stringify(pin, null, 2) + '\n', 'utf-8')
|
|
155
|
+
console.log(`Generated runtime-pin.json (runtime ${runtimeVersion}${policy ? `, policy ${policy}` : ''})`)
|
|
156
|
+
}
|
|
157
|
+
|
|
44
158
|
/**
|
|
45
159
|
* Build a self-contained ESM bundle for edge SSR (Cloudflare Dynamic Workers).
|
|
46
160
|
*
|
|
@@ -64,7 +178,7 @@ let _buildingSSRBundle = false
|
|
|
64
178
|
* file in, everything resolves. A future refactor can switch to side-
|
|
65
179
|
* loading runtime + React + core into the modules map separately so
|
|
66
180
|
* foundations stop carrying runtime in their bundles — see
|
|
67
|
-
* `kb/platform/plans/edge-
|
|
181
|
+
* `kb/platform/plans/edge-ssr-bundling-strategy.md`. Until then, this
|
|
68
182
|
* build pre-bundles for the isolate's contract.
|
|
69
183
|
*
|
|
70
184
|
* @param {string} outDir - Path to dist/ directory containing foundation.js
|
|
@@ -118,8 +232,16 @@ async function buildSSRBundle(outDir) {
|
|
|
118
232
|
// - @uniweb/theming (buildSectionOverrides, used by runtime/ssr)
|
|
119
233
|
//
|
|
120
234
|
// All in a single file so the Dynamic Worker isolate has one React instance.
|
|
235
|
+
// L2/L3 helpers from @uniweb/runtime/ssr that worker SSR + framework SSG
|
|
236
|
+
// both depend on. Keep this list in sync with runtime/src/ssr-renderer.js
|
|
237
|
+
// exports — missing one here makes the foundation bundle fail to import
|
|
238
|
+
// it ("module does not provide an export named X") inside the SSR isolate.
|
|
121
239
|
const ssrExports = runtimeSSRPath
|
|
122
|
-
? `export {
|
|
240
|
+
? `export {
|
|
241
|
+
initPrerender, initPrerenderForLocale,
|
|
242
|
+
renderPage, injectPageContent, prefetchIcons,
|
|
243
|
+
sliceContentForLocale, hydrateDataStore,
|
|
244
|
+
} from "${runtimeSSRPath.replace(/\\/g, '/')}";`
|
|
123
245
|
: ''
|
|
124
246
|
|
|
125
247
|
// Resolve React to a single package directory to avoid duplicate instances
|
|
@@ -191,6 +313,7 @@ export function foundationBuildPlugin(options = {}) {
|
|
|
191
313
|
|
|
192
314
|
let resolvedSrcDir
|
|
193
315
|
let resolvedOutDir
|
|
316
|
+
let resolvedRoot
|
|
194
317
|
let isProduction
|
|
195
318
|
|
|
196
319
|
return {
|
|
@@ -209,6 +332,7 @@ export function foundationBuildPlugin(options = {}) {
|
|
|
209
332
|
async configResolved(config) {
|
|
210
333
|
resolvedSrcDir = resolve(config.root, srcDir)
|
|
211
334
|
resolvedOutDir = config.build.outDir
|
|
335
|
+
resolvedRoot = config.root
|
|
212
336
|
isProduction = config.mode === 'production'
|
|
213
337
|
},
|
|
214
338
|
|
|
@@ -235,7 +359,17 @@ export function foundationBuildPlugin(options = {}) {
|
|
|
235
359
|
|
|
236
360
|
console.log(`Generated meta/schema.json with ${Object.keys(schema).length - 1} components`)
|
|
237
361
|
|
|
238
|
-
//
|
|
362
|
+
// Emit runtime-pin.json so the edge isolate (under Strategy S) can
|
|
363
|
+
// side-load the matching runtime/{ver}/ssr.js. Lands silently before
|
|
364
|
+
// the dual-mode resolver ships; foundations published in the dual-mode
|
|
365
|
+
// window already have the pin and start using the split-bundle path
|
|
366
|
+
// automatically once the edge is updated.
|
|
367
|
+
await emitRuntimePin(outDir, resolvedRoot)
|
|
368
|
+
|
|
369
|
+
// Build self-contained SSR bundle for edge rendering (Dynamic Workers).
|
|
370
|
+
// Stays in the build until Strategy S Phase 2 — dual-mode edge
|
|
371
|
+
// resolver continues to fall back to it for foundations without
|
|
372
|
+
// a runtime pin.
|
|
239
373
|
await buildSSRBundle(outDir)
|
|
240
374
|
},
|
|
241
375
|
|