@ossy/app 1.10.1 → 1.11.1
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/cli/build-terminal.js +343 -0
- package/cli/build.js +125 -44
- package/cli/dev.js +73 -15
- package/cli/prerender-react.task.js +67 -40
- package/package.json +10 -10
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import util from 'node:util'
|
|
2
|
+
|
|
3
|
+
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
4
|
+
|
|
5
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`
|
|
6
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`
|
|
7
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`
|
|
8
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`
|
|
9
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`
|
|
10
|
+
|
|
11
|
+
function stripAnsi (s) {
|
|
12
|
+
return String(s).replace(/\x1b\[[0-9;]*m/g, '')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function padVisible (s, width) {
|
|
16
|
+
const n = stripAnsi(s).length
|
|
17
|
+
return n >= width ? s : s + ' '.repeat(width - n)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function truncateVisible (s, maxW) {
|
|
21
|
+
const plain = stripAnsi(s)
|
|
22
|
+
if (plain.length <= maxW) return s
|
|
23
|
+
const cut = Math.max(0, maxW - 1)
|
|
24
|
+
return plain.slice(0, cut) + '…'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function pageIdFromHydrateEntryName (entryName) {
|
|
28
|
+
const p = String(entryName)
|
|
29
|
+
return p.startsWith('hydrate__') ? p.slice('hydrate__'.length) : p
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function fmtPart (part, shortLabel, frame) {
|
|
33
|
+
if (part.s === 'idle') return dim('—')
|
|
34
|
+
if (part.s === 'running') {
|
|
35
|
+
const sp = SPINNER[frame % SPINNER.length]
|
|
36
|
+
return `${yellow(sp)} ${dim(shortLabel + '…')}`
|
|
37
|
+
}
|
|
38
|
+
if (part.s === 'ok') return `${green('✔')} ${dim(`${part.ms}ms`)}`
|
|
39
|
+
if (part.s === 'fail') return `${red('✖')} ${dim(shortLabel)}`
|
|
40
|
+
if (part.s === 'skip') return dim(part.note ? `— ${part.note}` : '—')
|
|
41
|
+
return dim('—')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function rowLeadIcon (r, mode) {
|
|
45
|
+
if (mode === 'prerender-only') {
|
|
46
|
+
const p = r.prerender.s
|
|
47
|
+
if (p === 'fail') return red('✖')
|
|
48
|
+
if (p === 'running') return yellow('◐')
|
|
49
|
+
if (p === 'ok' || p === 'skip') return green('✔')
|
|
50
|
+
if (p === 'idle') return dim('·')
|
|
51
|
+
return green('✔')
|
|
52
|
+
}
|
|
53
|
+
const b = r.bundle.s
|
|
54
|
+
const p = r.prerender.s
|
|
55
|
+
if (b === 'fail' || p === 'fail') return red('✖')
|
|
56
|
+
if (b === 'running' || p === 'running') return yellow('◐')
|
|
57
|
+
if (b === 'ok' && p === 'idle') return yellow('◐')
|
|
58
|
+
if (b === 'ok' && (p === 'ok' || p === 'skip')) return green('✔')
|
|
59
|
+
if (b === 'idle' && p === 'idle') return dim('·')
|
|
60
|
+
return green('✔')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function useTty (stream) {
|
|
64
|
+
return (
|
|
65
|
+
stream.isTTY === true &&
|
|
66
|
+
process.env.TERM !== 'dumb' &&
|
|
67
|
+
process.env.CI !== 'true' &&
|
|
68
|
+
process.env.OSSY_PLAIN_OUTPUT !== '1'
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Merged overview + per-page progress, split layout: left = status table, right = log tail.
|
|
74
|
+
* TTY: single redraw block + optional console capture into the right column.
|
|
75
|
+
*/
|
|
76
|
+
export function createBuildDashboard ({
|
|
77
|
+
scope = '@ossy/app',
|
|
78
|
+
mode = 'full',
|
|
79
|
+
pageIds,
|
|
80
|
+
/** @type {Record<string, string>} route path per page id */
|
|
81
|
+
idToPath = {},
|
|
82
|
+
overview = { title: '@ossy/app', configRel: null, apiRoutes: [] },
|
|
83
|
+
stream = process.stdout,
|
|
84
|
+
} = {}) {
|
|
85
|
+
const ids = [...pageIds].sort()
|
|
86
|
+
const maxId = Math.max(6, ...ids.map((id) => String(id).length))
|
|
87
|
+
const tty = useTty(stream)
|
|
88
|
+
const termW = Math.max(60, stream.columns || 100)
|
|
89
|
+
const LEFT_W = Math.min(56, Math.max(38, Math.floor(termW * 0.42)))
|
|
90
|
+
const GAP = 2
|
|
91
|
+
const RIGHT_W = Math.max(16, termW - LEFT_W - GAP)
|
|
92
|
+
|
|
93
|
+
/** @type {Map<string, { bundle: object, prerender: object }>} */
|
|
94
|
+
const rows = new Map()
|
|
95
|
+
for (const id of ids) {
|
|
96
|
+
rows.set(id, {
|
|
97
|
+
bundle: { s: 'idle' },
|
|
98
|
+
prerender: { s: 'idle' },
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const logBuffer = []
|
|
103
|
+
const MAX_LOG = 120
|
|
104
|
+
let frame = 0
|
|
105
|
+
let spinTimer = null
|
|
106
|
+
let blockLines = 0
|
|
107
|
+
let captureActive = false
|
|
108
|
+
let savedConsole = null
|
|
109
|
+
|
|
110
|
+
const anyRunning = () => {
|
|
111
|
+
for (const r of rows.values()) {
|
|
112
|
+
if (r.bundle.s === 'running' || r.prerender.s === 'running') return true
|
|
113
|
+
}
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function pushLog (line) {
|
|
118
|
+
const s = String(line).trim() ? String(line) : ''
|
|
119
|
+
if (!s) return
|
|
120
|
+
if (!tty) {
|
|
121
|
+
stream.write(`${s}\n`)
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
logBuffer.push(dim(s))
|
|
125
|
+
if (logBuffer.length > MAX_LOG) logBuffer.splice(0, logBuffer.length - MAX_LOG)
|
|
126
|
+
redraw()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function leftHeaderLines () {
|
|
130
|
+
const out = []
|
|
131
|
+
out.push(bold(overview.title || `${scope} build`))
|
|
132
|
+
if (overview.configRel) {
|
|
133
|
+
out.push(`${dim('config')} ${truncateVisible(overview.configRel, LEFT_W - 10)}`)
|
|
134
|
+
}
|
|
135
|
+
const api = overview.apiRoutes || []
|
|
136
|
+
if (api.length === 0) {
|
|
137
|
+
/* noop */
|
|
138
|
+
} else if (api.length <= 2) {
|
|
139
|
+
for (const r of api) {
|
|
140
|
+
const line = `${dim('api')} ${truncateVisible(`${r.id} ${r.path}`, LEFT_W - 6)}`
|
|
141
|
+
out.push(line)
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
out.push(`${dim('api')} ${api.length} routes`)
|
|
145
|
+
}
|
|
146
|
+
out.push(dim('─'.repeat(Math.min(LEFT_W - 2, 44))))
|
|
147
|
+
return out
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function lineForPageRow (id) {
|
|
151
|
+
const r = rows.get(id)
|
|
152
|
+
const lead = rowLeadIcon(r, mode)
|
|
153
|
+
const pathStr = idToPath[id] != null ? dim(String(idToPath[id])) : ''
|
|
154
|
+
const idCol = padVisible(dim(String(id)), maxId)
|
|
155
|
+
const pathPad = padVisible(pathStr, 14)
|
|
156
|
+
const p = fmtPart(r.prerender, 'html', frame)
|
|
157
|
+
if (mode === 'prerender-only') {
|
|
158
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${p}`
|
|
159
|
+
}
|
|
160
|
+
const b = fmtPart(r.bundle, 'hydrate', frame)
|
|
161
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${padVisible(b, 20)} ${p}`
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildLeftColumnLines () {
|
|
165
|
+
const head = leftHeaderLines()
|
|
166
|
+
const body = ids.map((id) => lineForPageRow(id))
|
|
167
|
+
return [...head, ...body]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function buildHeaderOnlyLines () {
|
|
171
|
+
return leftHeaderLines()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Right column row i: logs bottom-aligned to the block height */
|
|
175
|
+
function rightColumnLine (i, totalRows) {
|
|
176
|
+
const start = logBuffer.length - totalRows + i
|
|
177
|
+
if (start < 0 || start >= logBuffer.length) return dim('·')
|
|
178
|
+
return truncateVisible(logBuffer[start], RIGHT_W)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function paintRow (leftLine, rightLine) {
|
|
182
|
+
const L = padVisible(truncateVisible(leftLine, LEFT_W), LEFT_W)
|
|
183
|
+
const R = truncateVisible(rightLine, RIGHT_W)
|
|
184
|
+
return `${L}${' '.repeat(GAP)}${R}\n`
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function redraw () {
|
|
188
|
+
if (!tty) return
|
|
189
|
+
const leftCol = buildLeftColumnLines()
|
|
190
|
+
const n = leftCol.length
|
|
191
|
+
const lines = []
|
|
192
|
+
for (let i = 0; i < n; i++) {
|
|
193
|
+
lines.push(paintRow(leftCol[i], rightColumnLine(i, n)))
|
|
194
|
+
}
|
|
195
|
+
if (blockLines === 0) {
|
|
196
|
+
for (const ln of lines) stream.write(ln)
|
|
197
|
+
blockLines = lines.length
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
stream.write(`\x1b[${blockLines}A`)
|
|
201
|
+
for (const ln of lines) {
|
|
202
|
+
stream.write(`\x1b[2K\r${ln}`)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function ensureSpin () {
|
|
207
|
+
if (!tty || spinTimer) return
|
|
208
|
+
spinTimer = setInterval(() => {
|
|
209
|
+
frame += 1
|
|
210
|
+
redraw()
|
|
211
|
+
}, 80)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function stopSpin () {
|
|
215
|
+
if (spinTimer) {
|
|
216
|
+
clearInterval(spinTimer)
|
|
217
|
+
spinTimer = null
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function nonTtyLine (id, phase, ok, ms, err) {
|
|
222
|
+
const label = phase === 'bundle' ? 'hydrate' : 'prerender'
|
|
223
|
+
const icon = ok ? green('✔') : red('✖')
|
|
224
|
+
const time = ms != null ? dim(` (${ms}ms)`) : ''
|
|
225
|
+
stream.write(`${icon} ${dim(`${scope}:${label}:`)}${id}${time}\n`)
|
|
226
|
+
if (err && !ok) stream.write(` ${red(String(err.message || err))}\n`)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function beginCapture () {
|
|
230
|
+
if (!tty || captureActive) return
|
|
231
|
+
captureActive = true
|
|
232
|
+
savedConsole = {
|
|
233
|
+
log: console.log,
|
|
234
|
+
warn: console.warn,
|
|
235
|
+
info: console.info,
|
|
236
|
+
error: console.error,
|
|
237
|
+
}
|
|
238
|
+
const fmt = (...a) => util.format(...a)
|
|
239
|
+
console.log = (...a) => {
|
|
240
|
+
pushLog(`[log] ${fmt(...a)}`)
|
|
241
|
+
}
|
|
242
|
+
console.warn = (...a) => {
|
|
243
|
+
pushLog(`[warn] ${fmt(...a)}`)
|
|
244
|
+
}
|
|
245
|
+
console.info = (...a) => {
|
|
246
|
+
pushLog(`[info] ${fmt(...a)}`)
|
|
247
|
+
}
|
|
248
|
+
console.error = (...a) => {
|
|
249
|
+
const msg = fmt(...a)
|
|
250
|
+
pushLog(`[error] ${msg}`)
|
|
251
|
+
savedConsole.error(`[@ossy/app] ${msg}`)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function endCapture () {
|
|
256
|
+
if (!captureActive || !savedConsole) return
|
|
257
|
+
console.log = savedConsole.log
|
|
258
|
+
console.warn = savedConsole.warn
|
|
259
|
+
console.info = savedConsole.info
|
|
260
|
+
console.error = savedConsole.error
|
|
261
|
+
savedConsole = null
|
|
262
|
+
captureActive = false
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
pushLog,
|
|
267
|
+
|
|
268
|
+
/** Start optional console hijack + first paint (TTY). Plain header only when not a TTY. */
|
|
269
|
+
start () {
|
|
270
|
+
if (!tty) {
|
|
271
|
+
for (const ln of buildHeaderOnlyLines()) {
|
|
272
|
+
stream.write(`${ln}\n`)
|
|
273
|
+
}
|
|
274
|
+
stream.write('\n')
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
beginCapture()
|
|
278
|
+
redraw()
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
startBundle (pageId) {
|
|
282
|
+
if (mode === 'prerender-only') return
|
|
283
|
+
const r = rows.get(pageId)
|
|
284
|
+
if (!r) return
|
|
285
|
+
r.bundle = { s: 'running' }
|
|
286
|
+
ensureSpin()
|
|
287
|
+
redraw()
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
completeBundle (pageId, { ok, ms, error }) {
|
|
291
|
+
if (mode === 'prerender-only') return
|
|
292
|
+
const r = rows.get(pageId)
|
|
293
|
+
if (!r) return
|
|
294
|
+
r.bundle = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
295
|
+
if (!ok) {
|
|
296
|
+
r.prerender = { s: 'skip', note: 'bundle failed' }
|
|
297
|
+
if (!tty) nonTtyLine(pageId, 'bundle', false, ms, error)
|
|
298
|
+
}
|
|
299
|
+
if (!anyRunning()) stopSpin()
|
|
300
|
+
redraw()
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
startPrerender (pageId) {
|
|
304
|
+
const r = rows.get(pageId)
|
|
305
|
+
if (!r || r.prerender.s === 'skip') return
|
|
306
|
+
r.prerender = { s: 'running' }
|
|
307
|
+
ensureSpin()
|
|
308
|
+
redraw()
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
completePrerender (pageId, { ok, ms, error }) {
|
|
312
|
+
const r = rows.get(pageId)
|
|
313
|
+
if (!r || r.prerender.s === 'skip') return
|
|
314
|
+
r.prerender = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
315
|
+
if (!tty) nonTtyLine(pageId, 'prerender', ok, ms, error)
|
|
316
|
+
if (!anyRunning()) stopSpin()
|
|
317
|
+
redraw()
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
skipPrerender (pageId, note) {
|
|
321
|
+
const r = rows.get(pageId)
|
|
322
|
+
if (!r) return
|
|
323
|
+
if (r.bundle.s === 'fail') return
|
|
324
|
+
r.prerender = { s: 'skip', note: note || 'skipped' }
|
|
325
|
+
if (!tty) stream.write(`${dim('—')} ${scope}:prerender:${pageId} (${note})\n`)
|
|
326
|
+
redraw()
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
printSectionTitle () {
|
|
330
|
+
/* merged into overview.title — no-op for API compat */
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
dispose () {
|
|
334
|
+
stopSpin()
|
|
335
|
+
endCapture()
|
|
336
|
+
if (tty && blockLines > 0) {
|
|
337
|
+
redraw()
|
|
338
|
+
stream.write('\n')
|
|
339
|
+
blockLines = 0
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
}
|
|
343
|
+
}
|
package/cli/build.js
CHANGED
|
@@ -12,6 +12,7 @@ import copy from 'rollup-plugin-copy';
|
|
|
12
12
|
import replace from '@rollup/plugin-replace';
|
|
13
13
|
import arg from 'arg'
|
|
14
14
|
import prerenderReactTask from './prerender-react.task.js'
|
|
15
|
+
import { createBuildDashboard } from './build-terminal.js'
|
|
15
16
|
|
|
16
17
|
export const PAGE_FILE_PATTERN = /\.page\.(jsx?|tsx?)$/
|
|
17
18
|
export const API_FILE_PATTERN = /\.api\.(mjs|cjs|js)$/
|
|
@@ -209,10 +210,17 @@ export function createOssyClientRollupPlugins ({ nodeEnv, copyPublicFrom, buildP
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
/** Bundles a single Node ESM file (inline dynamic imports) for SSR / API / tasks. */
|
|
212
|
-
export async function bundleOssyNodeEntry ({ inputPath, outputFile, nodeEnv }) {
|
|
213
|
+
export async function bundleOssyNodeEntry ({ inputPath, outputFile, nodeEnv, onWarn }) {
|
|
213
214
|
const bundle = await rollup({
|
|
214
215
|
input: inputPath,
|
|
215
216
|
plugins: createOssyAppBundlePlugins({ nodeEnv }),
|
|
217
|
+
onwarn (warning, defaultHandler) {
|
|
218
|
+
if (onWarn) {
|
|
219
|
+
onWarn(warning)
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
defaultHandler(warning)
|
|
223
|
+
},
|
|
216
224
|
})
|
|
217
225
|
await bundle.write({
|
|
218
226
|
file: outputFile,
|
|
@@ -544,24 +552,46 @@ export function parsePagesFromSource(filePath) {
|
|
|
544
552
|
}
|
|
545
553
|
}
|
|
546
554
|
|
|
547
|
-
|
|
555
|
+
/**
|
|
556
|
+
* Same facts as the old build overview printout, for dashboards / plain logging.
|
|
557
|
+
*/
|
|
558
|
+
export function getBuildOverviewSnapshot ({
|
|
548
559
|
pagesSourcePath,
|
|
549
560
|
apiSourcePath,
|
|
550
561
|
apiOverviewFiles = [],
|
|
551
562
|
configPath,
|
|
552
563
|
pageFiles,
|
|
553
564
|
}) {
|
|
554
|
-
const rel = (p) => p ? path.relative(process.cwd(), p) : undefined
|
|
565
|
+
const rel = (p) => (p ? path.relative(process.cwd(), p) : undefined)
|
|
555
566
|
const srcDir = path.resolve(process.cwd(), 'src')
|
|
556
|
-
|
|
557
|
-
if (fs.existsSync(configPath)) {
|
|
558
|
-
console.log(` \x1b[36mConfig:\x1b[0m ${rel(configPath)}`)
|
|
559
|
-
}
|
|
560
|
-
console.log(' ' + '─'.repeat(50))
|
|
567
|
+
const configRel = fs.existsSync(configPath) ? rel(configPath) : null
|
|
561
568
|
|
|
562
569
|
const pages = pageFiles?.length
|
|
563
570
|
? pageFiles.map((f) => filePathToRoute(f, srcDir))
|
|
564
571
|
: parsePagesFromSource(pagesSourcePath)
|
|
572
|
+
|
|
573
|
+
const apiFilesToScan =
|
|
574
|
+
apiOverviewFiles?.length > 0
|
|
575
|
+
? apiOverviewFiles
|
|
576
|
+
: fs.existsSync(apiSourcePath)
|
|
577
|
+
? [apiSourcePath]
|
|
578
|
+
: []
|
|
579
|
+
const apiRoutes = []
|
|
580
|
+
for (const f of apiFilesToScan) {
|
|
581
|
+
if (fs.existsSync(f)) apiRoutes.push(...parsePagesFromSource(f))
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return { configRel, pages, apiRoutes }
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export function printBuildOverview (opts) {
|
|
588
|
+
const { configRel, pages, apiRoutes } = getBuildOverviewSnapshot(opts)
|
|
589
|
+
console.log('\n \x1b[1mBuild overview\x1b[0m')
|
|
590
|
+
if (configRel) {
|
|
591
|
+
console.log(` \x1b[36mConfig:\x1b[0m ${configRel}`)
|
|
592
|
+
}
|
|
593
|
+
console.log(' ' + '─'.repeat(50))
|
|
594
|
+
|
|
565
595
|
if (pages.length > 0) {
|
|
566
596
|
console.log(' \x1b[36mRoutes:\x1b[0m')
|
|
567
597
|
const maxId = Math.max(6, ...pages.map((p) => String(p.id).length))
|
|
@@ -575,16 +605,6 @@ export function printBuildOverview({
|
|
|
575
605
|
console.log(' \x1b[33mRoutes:\x1b[0m (could not parse or empty)')
|
|
576
606
|
}
|
|
577
607
|
|
|
578
|
-
const apiFilesToScan =
|
|
579
|
-
apiOverviewFiles?.length > 0
|
|
580
|
-
? apiOverviewFiles
|
|
581
|
-
: fs.existsSync(apiSourcePath)
|
|
582
|
-
? [apiSourcePath]
|
|
583
|
-
: []
|
|
584
|
-
const apiRoutes = []
|
|
585
|
-
for (const f of apiFilesToScan) {
|
|
586
|
-
if (fs.existsSync(f)) apiRoutes.push(...parsePagesFromSource(f))
|
|
587
|
-
}
|
|
588
608
|
if (apiRoutes.length > 0) {
|
|
589
609
|
console.log(' \x1b[36mAPI routes:\x1b[0m')
|
|
590
610
|
apiRoutes.forEach((r) => {
|
|
@@ -600,9 +620,6 @@ export const build = async (cliArgs) => {
|
|
|
600
620
|
'-c': '--config',
|
|
601
621
|
}, { argv: cliArgs })
|
|
602
622
|
|
|
603
|
-
console.log('[@ossy/app][build] Starting...')
|
|
604
|
-
|
|
605
|
-
|
|
606
623
|
const scriptDir = path.dirname(url.fileURLToPath(import.meta.url))
|
|
607
624
|
const buildPath = path.resolve('build')
|
|
608
625
|
const srcDir = path.resolve('src')
|
|
@@ -611,7 +628,10 @@ export const build = async (cliArgs) => {
|
|
|
611
628
|
|
|
612
629
|
resetOssyBuildDir(buildPath)
|
|
613
630
|
|
|
614
|
-
writeResourceTemplatesBarrelIfPresent({
|
|
631
|
+
const resourceTemplatesResult = writeResourceTemplatesBarrelIfPresent({
|
|
632
|
+
cwd: process.cwd(),
|
|
633
|
+
log: false,
|
|
634
|
+
})
|
|
615
635
|
|
|
616
636
|
const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
|
|
617
637
|
|
|
@@ -634,14 +654,6 @@ export const build = async (cliArgs) => {
|
|
|
634
654
|
let middlewareSourcePath = path.resolve('src/middleware.js');
|
|
635
655
|
const publicDir = path.resolve('public')
|
|
636
656
|
|
|
637
|
-
printBuildOverview({
|
|
638
|
-
pagesSourcePath: pagesGeneratedPath,
|
|
639
|
-
apiSourcePath,
|
|
640
|
-
apiOverviewFiles,
|
|
641
|
-
configPath,
|
|
642
|
-
pageFiles,
|
|
643
|
-
});
|
|
644
|
-
|
|
645
657
|
if (!fs.existsSync(middlewareSourcePath)) {
|
|
646
658
|
middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
|
|
647
659
|
}
|
|
@@ -654,21 +666,82 @@ export const build = async (cliArgs) => {
|
|
|
654
666
|
const apiBundlePath = path.join(ossyDir, OSSY_API_SERVER_BUNDLE)
|
|
655
667
|
const tasksBundlePath = path.join(ossyDir, OSSY_TASKS_SERVER_BUNDLE)
|
|
656
668
|
|
|
669
|
+
const useDashboard = Object.keys(clientHydrateInput).length > 0
|
|
670
|
+
const overviewSnap = getBuildOverviewSnapshot({
|
|
671
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
672
|
+
apiSourcePath,
|
|
673
|
+
apiOverviewFiles,
|
|
674
|
+
configPath,
|
|
675
|
+
pageFiles,
|
|
676
|
+
})
|
|
677
|
+
const idToPath = Object.fromEntries(
|
|
678
|
+
pageFiles.map((f) => [
|
|
679
|
+
clientHydrateIdForPage(f, srcDir),
|
|
680
|
+
filePathToRoute(f, srcDir).path,
|
|
681
|
+
])
|
|
682
|
+
)
|
|
683
|
+
const pageIds = useDashboard
|
|
684
|
+
? [...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir)))].sort()
|
|
685
|
+
: []
|
|
686
|
+
|
|
687
|
+
let dashboard = null
|
|
688
|
+
if (useDashboard && pageIds.length > 0) {
|
|
689
|
+
dashboard = createBuildDashboard({
|
|
690
|
+
mode: 'full',
|
|
691
|
+
pageIds,
|
|
692
|
+
idToPath,
|
|
693
|
+
overview: {
|
|
694
|
+
title: '@ossy/app build',
|
|
695
|
+
configRel: overviewSnap.configRel,
|
|
696
|
+
apiRoutes: overviewSnap.apiRoutes,
|
|
697
|
+
},
|
|
698
|
+
})
|
|
699
|
+
dashboard.start()
|
|
700
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
701
|
+
dashboard.pushLog(
|
|
702
|
+
`[resource-templates] merged ${resourceTemplatesResult.count} → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
703
|
+
)
|
|
704
|
+
}
|
|
705
|
+
} else {
|
|
706
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild\x1b[0m')
|
|
707
|
+
printBuildOverview({
|
|
708
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
709
|
+
apiSourcePath,
|
|
710
|
+
apiOverviewFiles,
|
|
711
|
+
configPath,
|
|
712
|
+
pageFiles,
|
|
713
|
+
})
|
|
714
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
715
|
+
console.log(
|
|
716
|
+
`[@ossy/app][resource-templates] merged ${resourceTemplatesResult.count} template(s) → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
717
|
+
)
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const warnSink = dashboard
|
|
722
|
+
? (w) => {
|
|
723
|
+
dashboard.pushLog(`rollup: ${w.message}`)
|
|
724
|
+
}
|
|
725
|
+
: undefined
|
|
726
|
+
|
|
657
727
|
await bundleOssyNodeEntry({
|
|
658
728
|
inputPath: pagesGeneratedPath,
|
|
659
729
|
outputFile: pagesBundlePath,
|
|
660
730
|
nodeEnv: 'production',
|
|
731
|
+
onWarn: warnSink,
|
|
661
732
|
})
|
|
662
733
|
await bundleOssyNodeEntry({
|
|
663
734
|
inputPath: apiSourcePath,
|
|
664
735
|
outputFile: apiBundlePath,
|
|
665
736
|
nodeEnv: 'production',
|
|
737
|
+
onWarn: warnSink,
|
|
666
738
|
})
|
|
667
739
|
const { taskSourcePath } = resolveTaskSource({ srcDir, buildPath })
|
|
668
740
|
await bundleOssyNodeEntry({
|
|
669
741
|
inputPath: taskSourcePath,
|
|
670
742
|
outputFile: tasksBundlePath,
|
|
671
743
|
nodeEnv: 'production',
|
|
744
|
+
onWarn: warnSink,
|
|
672
745
|
})
|
|
673
746
|
|
|
674
747
|
writeAppRuntimeShims({
|
|
@@ -677,20 +750,28 @@ export const build = async (cliArgs) => {
|
|
|
677
750
|
})
|
|
678
751
|
copyOssyAppRuntime({ scriptDir, buildPath })
|
|
679
752
|
|
|
680
|
-
if (
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
753
|
+
if (useDashboard && dashboard) {
|
|
754
|
+
try {
|
|
755
|
+
await prerenderReactTask.handler({
|
|
756
|
+
op: 'runProduction',
|
|
757
|
+
clientHydrateInput,
|
|
758
|
+
pageFilesLength: pageFiles.length,
|
|
759
|
+
copyPublicFrom: publicDir,
|
|
760
|
+
buildPath,
|
|
761
|
+
nodeEnv: 'production',
|
|
762
|
+
pagesBundlePath,
|
|
763
|
+
configSourcePath,
|
|
764
|
+
createClientRollupPlugins: createOssyClientRollupPlugins,
|
|
765
|
+
minifyBrowserStaticChunks,
|
|
766
|
+
reporter: dashboard,
|
|
767
|
+
})
|
|
768
|
+
} finally {
|
|
769
|
+
dashboard.dispose()
|
|
770
|
+
}
|
|
693
771
|
}
|
|
694
772
|
|
|
695
|
-
|
|
773
|
+
if (useDashboard && dashboard) {
|
|
774
|
+
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
775
|
+
}
|
|
776
|
+
console.log(' \x1b[32m✔\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild finished\x1b[0m\n')
|
|
696
777
|
};
|
package/cli/dev.js
CHANGED
|
@@ -3,6 +3,8 @@ import url from 'url';
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import {
|
|
5
5
|
printBuildOverview,
|
|
6
|
+
getBuildOverviewSnapshot,
|
|
7
|
+
filePathToRoute,
|
|
6
8
|
discoverFilesByPattern,
|
|
7
9
|
PAGE_FILE_PATTERN,
|
|
8
10
|
generatePagesModule,
|
|
@@ -29,14 +31,13 @@ import {
|
|
|
29
31
|
OSSY_RESOURCE_TEMPLATES_OUT,
|
|
30
32
|
} from './build.js';
|
|
31
33
|
import prerenderReactTask from './prerender-react.task.js'
|
|
34
|
+
import { createBuildDashboard } from './build-terminal.js'
|
|
32
35
|
import { watch } from 'rollup';
|
|
33
36
|
import arg from 'arg'
|
|
34
37
|
import { spawn } from 'node:child_process'
|
|
35
38
|
// import inject from '@rollup/plugin-inject'
|
|
36
39
|
|
|
37
40
|
export const dev = async (cliArgs) => {
|
|
38
|
-
console.log('[@ossy/app][dev] Starting...')
|
|
39
|
-
|
|
40
41
|
const options = arg({
|
|
41
42
|
'--config': String,
|
|
42
43
|
'-c': '--config',
|
|
@@ -51,7 +52,11 @@ export const dev = async (cliArgs) => {
|
|
|
51
52
|
|
|
52
53
|
resetOssyBuildDir(buildPath)
|
|
53
54
|
|
|
54
|
-
writeResourceTemplatesBarrelIfPresent({
|
|
55
|
+
const resourceTemplatesResult = writeResourceTemplatesBarrelIfPresent({
|
|
56
|
+
cwd: process.cwd(),
|
|
57
|
+
log: false,
|
|
58
|
+
})
|
|
59
|
+
let resourceTemplatesDevLogged = false
|
|
55
60
|
|
|
56
61
|
const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
|
|
57
62
|
fs.writeFileSync(
|
|
@@ -74,13 +79,21 @@ export const dev = async (cliArgs) => {
|
|
|
74
79
|
let middlewareSourcePath = path.resolve(options['--middleware-source'] || 'src/middleware.js');
|
|
75
80
|
const publicDir = path.resolve('public')
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
if (pageFiles.length === 0) {
|
|
83
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mdev\x1b[0m')
|
|
84
|
+
printBuildOverview({
|
|
85
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
86
|
+
apiSourcePath,
|
|
87
|
+
apiOverviewFiles,
|
|
88
|
+
configPath,
|
|
89
|
+
pageFiles,
|
|
90
|
+
})
|
|
91
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
92
|
+
console.log(
|
|
93
|
+
`[@ossy/app][resource-templates] merged ${resourceTemplatesResult.count} template(s) → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
84
97
|
|
|
85
98
|
if (!fs.existsSync(middlewareSourcePath)) {
|
|
86
99
|
middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
|
|
@@ -225,13 +238,15 @@ export const dev = async (cliArgs) => {
|
|
|
225
238
|
|
|
226
239
|
watcher.on('event', async (event) => {
|
|
227
240
|
if (event.code === 'BUNDLE_START') {
|
|
228
|
-
console.log('[@ossy/app
|
|
241
|
+
console.log(' \x1b[2m◐\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mrollup watch …\x1b[0m')
|
|
229
242
|
}
|
|
230
243
|
if (event.code === 'ERROR') {
|
|
231
|
-
console.error('[@ossy/app
|
|
244
|
+
console.error(' \x1b[31m✖\x1b[0m \x1b[1m@ossy/app\x1b[0m build error', event.error)
|
|
232
245
|
}
|
|
233
246
|
if (event.code === 'BUNDLE_END') {
|
|
234
|
-
console.log(
|
|
247
|
+
console.log(
|
|
248
|
+
` \x1b[32m✔\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mbundles\x1b[0m \x1b[2m(${event.duration}ms)\x1b[0m`
|
|
249
|
+
)
|
|
235
250
|
}
|
|
236
251
|
if (event.code === 'END') {
|
|
237
252
|
writeAppRuntimeShims({
|
|
@@ -240,15 +255,58 @@ export const dev = async (cliArgs) => {
|
|
|
240
255
|
})
|
|
241
256
|
copyOssyAppRuntime({ scriptDir, buildPath })
|
|
242
257
|
if (pageFiles.length > 0) {
|
|
258
|
+
const pageIds = [
|
|
259
|
+
...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir))),
|
|
260
|
+
].sort()
|
|
261
|
+
const overviewSnap = getBuildOverviewSnapshot({
|
|
262
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
263
|
+
apiSourcePath,
|
|
264
|
+
apiOverviewFiles,
|
|
265
|
+
configPath,
|
|
266
|
+
pageFiles,
|
|
267
|
+
})
|
|
268
|
+
const idToPath = Object.fromEntries(
|
|
269
|
+
pageFiles.map((f) => [
|
|
270
|
+
clientHydrateIdForPage(f, srcDir),
|
|
271
|
+
filePathToRoute(f, srcDir).path,
|
|
272
|
+
])
|
|
273
|
+
)
|
|
274
|
+
const reporter = pageIds.length
|
|
275
|
+
? createBuildDashboard({
|
|
276
|
+
mode: 'prerender-only',
|
|
277
|
+
pageIds,
|
|
278
|
+
idToPath,
|
|
279
|
+
overview: {
|
|
280
|
+
title: '@ossy/app dev',
|
|
281
|
+
configRel: overviewSnap.configRel,
|
|
282
|
+
apiRoutes: overviewSnap.apiRoutes,
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
: null
|
|
286
|
+
reporter?.start()
|
|
287
|
+
if (
|
|
288
|
+
!resourceTemplatesDevLogged &&
|
|
289
|
+
resourceTemplatesResult.wrote &&
|
|
290
|
+
resourceTemplatesResult.path &&
|
|
291
|
+
reporter
|
|
292
|
+
) {
|
|
293
|
+
reporter.pushLog(
|
|
294
|
+
`[resource-templates] merged ${resourceTemplatesResult.count} → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
295
|
+
)
|
|
296
|
+
resourceTemplatesDevLogged = true
|
|
297
|
+
}
|
|
243
298
|
try {
|
|
244
299
|
await prerenderReactTask.handler({
|
|
245
300
|
op: 'prerenderPagesParallel',
|
|
246
301
|
pagesBundlePath,
|
|
247
302
|
configSourcePath,
|
|
248
303
|
publicDir: path.join(buildPath, 'public'),
|
|
304
|
+
reporter,
|
|
249
305
|
})
|
|
250
306
|
} catch (err) {
|
|
251
|
-
console.error('[@ossy/app
|
|
307
|
+
console.error(' \x1b[31m✖\x1b[0m \x1b[1m@ossy/app\x1b[0m prerender failed', err)
|
|
308
|
+
} finally {
|
|
309
|
+
reporter?.dispose()
|
|
252
310
|
}
|
|
253
311
|
}
|
|
254
312
|
scheduleRestart()
|
|
@@ -297,7 +355,7 @@ export const dev = async (cliArgs) => {
|
|
|
297
355
|
}
|
|
298
356
|
const norm = filename.replace(/\\/g, '/')
|
|
299
357
|
if (/\.resource\.js$/.test(norm) && norm.includes('resource-templates/')) {
|
|
300
|
-
writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log:
|
|
358
|
+
writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log: false })
|
|
301
359
|
const rtOut = path.join(resourceTemplatesDir(process.cwd()), OSSY_RESOURCE_TEMPLATES_OUT)
|
|
302
360
|
if (fs.existsSync(rtOut) && typeof watcher?.invalidate === 'function') {
|
|
303
361
|
watcher.invalidate(rtOut)
|
|
@@ -3,6 +3,7 @@ import url from 'url'
|
|
|
3
3
|
import fs from 'fs'
|
|
4
4
|
import { rollup } from 'rollup'
|
|
5
5
|
import { BuildPage } from './render-page.task.js'
|
|
6
|
+
import { pageIdFromHydrateEntryName } from './build-terminal.js'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Maps an app route path to the file path express.static will serve for that URL
|
|
@@ -103,6 +104,7 @@ async function bundleHydratePagesParallel ({
|
|
|
103
104
|
buildPathForPlugins,
|
|
104
105
|
createClientRollupPlugins,
|
|
105
106
|
minifyBrowserStaticChunks,
|
|
107
|
+
reporter,
|
|
106
108
|
}) {
|
|
107
109
|
copyPublicToBuild({ copyPublicFrom, buildPath })
|
|
108
110
|
fs.mkdirSync(path.join(buildPath, 'public', 'static'), { recursive: true })
|
|
@@ -110,29 +112,37 @@ async function bundleHydratePagesParallel ({
|
|
|
110
112
|
const entries = Object.entries(clientHydrateInput)
|
|
111
113
|
|
|
112
114
|
const results = await Promise.allSettled(
|
|
113
|
-
entries.map(([entryName, stubPath]) => {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
entries.map(async ([entryName, stubPath]) => {
|
|
116
|
+
const pageId = pageIdFromHydrateEntryName(entryName)
|
|
117
|
+
const t0 = Date.now()
|
|
118
|
+
reporter?.startBundle?.(pageId)
|
|
119
|
+
try {
|
|
120
|
+
const plugins = createClientRollupPlugins({
|
|
121
|
+
nodeEnv,
|
|
122
|
+
copyPublicFrom: undefined,
|
|
123
|
+
buildPath: buildPathForPlugins,
|
|
124
|
+
})
|
|
125
|
+
await bundleOneHydratePage({
|
|
126
|
+
entryName,
|
|
127
|
+
stubPath,
|
|
128
|
+
buildPath,
|
|
129
|
+
plugins,
|
|
130
|
+
minifyPlugin: minifyBrowserStaticChunks(),
|
|
131
|
+
})
|
|
132
|
+
reporter?.completeBundle?.(pageId, { ok: true, ms: Date.now() - t0 })
|
|
133
|
+
} catch (error) {
|
|
134
|
+
reporter?.completeBundle?.(pageId, {
|
|
135
|
+
ok: false,
|
|
136
|
+
ms: Date.now() - t0,
|
|
137
|
+
error,
|
|
138
|
+
})
|
|
139
|
+
console.error(`[@ossy/app][client-bundle] ${entryName} failed:`, error)
|
|
140
|
+
throw error
|
|
141
|
+
}
|
|
126
142
|
})
|
|
127
143
|
)
|
|
128
144
|
|
|
129
145
|
const failures = countSettledFailures(results)
|
|
130
|
-
results.forEach((r, i) => {
|
|
131
|
-
if (r.status === 'rejected') {
|
|
132
|
-
const [entryName] = entries[i]
|
|
133
|
-
console.error(`[@ossy/app][client-bundle] ${entryName} failed:`, r.reason)
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
146
|
|
|
137
147
|
return { results, failures }
|
|
138
148
|
}
|
|
@@ -157,15 +167,13 @@ async function prerenderOnePage ({
|
|
|
157
167
|
const outPath = staticHtmlPathForRoute(route.path, publicDir)
|
|
158
168
|
fs.mkdirSync(path.dirname(outPath), { recursive: true })
|
|
159
169
|
fs.writeFileSync(outPath, html, 'utf8')
|
|
160
|
-
console.log(
|
|
161
|
-
`[@ossy/app][prerender] ${route.path} → ${path.relative(process.cwd(), outPath)}`
|
|
162
|
-
)
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
async function prerenderPagesParallel ({
|
|
166
173
|
pagesBundlePath,
|
|
167
174
|
configSourcePath,
|
|
168
175
|
publicDir,
|
|
176
|
+
reporter,
|
|
169
177
|
}) {
|
|
170
178
|
const cfgHref = url.pathToFileURL(path.resolve(configSourcePath)).href
|
|
171
179
|
const pagesHref = url.pathToFileURL(path.resolve(pagesBundlePath)).href
|
|
@@ -180,6 +188,10 @@ async function prerenderPagesParallel ({
|
|
|
180
188
|
for (const route of pageList) {
|
|
181
189
|
if (!route?.element) continue
|
|
182
190
|
if (!pathIsPrerenderable(route.path)) {
|
|
191
|
+
reporter?.skipPrerender?.(
|
|
192
|
+
route.id,
|
|
193
|
+
`not static (${JSON.stringify(route.path)})`
|
|
194
|
+
)
|
|
183
195
|
console.warn(
|
|
184
196
|
`[@ossy/app][prerender] Skipping "${route.id}" (path not prerenderable: ${JSON.stringify(route.path)})`
|
|
185
197
|
)
|
|
@@ -189,25 +201,32 @@ async function prerenderPagesParallel ({
|
|
|
189
201
|
}
|
|
190
202
|
|
|
191
203
|
const results = await Promise.allSettled(
|
|
192
|
-
routesToRender.map((route) =>
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
204
|
+
routesToRender.map(async (route) => {
|
|
205
|
+
const t0 = Date.now()
|
|
206
|
+
reporter?.startPrerender?.(route.id)
|
|
207
|
+
try {
|
|
208
|
+
await prerenderOnePage({
|
|
209
|
+
route,
|
|
210
|
+
buildTimeConfig,
|
|
211
|
+
pageList,
|
|
212
|
+
publicDir,
|
|
213
|
+
})
|
|
214
|
+
reporter?.completePrerender?.(route.id, { ok: true, ms: Date.now() - t0 })
|
|
215
|
+
} catch (error) {
|
|
216
|
+
reporter?.completePrerender?.(route.id, {
|
|
217
|
+
ok: false,
|
|
218
|
+
ms: Date.now() - t0,
|
|
219
|
+
error,
|
|
220
|
+
})
|
|
221
|
+
console.error(
|
|
222
|
+
`[@ossy/app][prerender] "${route?.id}" (${route?.path}) failed:`,
|
|
223
|
+
error
|
|
224
|
+
)
|
|
225
|
+
throw error
|
|
226
|
+
}
|
|
227
|
+
})
|
|
200
228
|
)
|
|
201
229
|
const failures = countSettledFailures(results)
|
|
202
|
-
results.forEach((r, i) => {
|
|
203
|
-
if (r.status === 'rejected') {
|
|
204
|
-
const route = routesToRender[i]
|
|
205
|
-
console.error(
|
|
206
|
-
`[@ossy/app][prerender] "${route?.id}" (${route?.path}) failed:`,
|
|
207
|
-
r.reason
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
230
|
|
|
212
231
|
return { results, failures }
|
|
213
232
|
}
|
|
@@ -222,6 +241,7 @@ async function runProduction ({
|
|
|
222
241
|
configSourcePath,
|
|
223
242
|
createClientRollupPlugins,
|
|
224
243
|
minifyBrowserStaticChunks,
|
|
244
|
+
reporter,
|
|
225
245
|
}) {
|
|
226
246
|
if (pageFilesLength === 0 || Object.keys(clientHydrateInput).length === 0) {
|
|
227
247
|
return { bundleFailures: 0, prerenderFailures: 0 }
|
|
@@ -235,12 +255,14 @@ async function runProduction ({
|
|
|
235
255
|
buildPathForPlugins: buildPath,
|
|
236
256
|
createClientRollupPlugins,
|
|
237
257
|
minifyBrowserStaticChunks,
|
|
258
|
+
reporter,
|
|
238
259
|
})
|
|
239
260
|
|
|
240
261
|
const { failures: prerenderFailures } = await prerenderPagesParallel({
|
|
241
262
|
pagesBundlePath,
|
|
242
263
|
configSourcePath,
|
|
243
264
|
publicDir: path.join(buildPath, 'public'),
|
|
265
|
+
reporter,
|
|
244
266
|
})
|
|
245
267
|
|
|
246
268
|
if (bundleFailures + prerenderFailures > 0) {
|
|
@@ -261,7 +283,12 @@ export default {
|
|
|
261
283
|
return runProduction(input)
|
|
262
284
|
}
|
|
263
285
|
if (op === 'prerenderPagesParallel') {
|
|
264
|
-
return prerenderPagesParallel(
|
|
286
|
+
return prerenderPagesParallel({
|
|
287
|
+
pagesBundlePath: input.pagesBundlePath,
|
|
288
|
+
configSourcePath: input.configSourcePath,
|
|
289
|
+
publicDir: input.publicDir,
|
|
290
|
+
reporter: input.reporter,
|
|
291
|
+
})
|
|
265
292
|
}
|
|
266
293
|
throw new Error(
|
|
267
294
|
`[@ossy/app][prerender-react] Unknown op: ${String(op)} (expected runProduction | prerenderPagesParallel)`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"@babel/eslint-parser": "^7.15.8",
|
|
28
28
|
"@babel/preset-react": "^7.26.3",
|
|
29
29
|
"@babel/register": "^7.25.9",
|
|
30
|
-
"@ossy/connected-components": "^1.
|
|
31
|
-
"@ossy/design-system": "^1.
|
|
32
|
-
"@ossy/pages": "^1.
|
|
33
|
-
"@ossy/router": "^1.
|
|
34
|
-
"@ossy/router-react": "^1.
|
|
35
|
-
"@ossy/sdk": "^1.
|
|
36
|
-
"@ossy/sdk-react": "^1.
|
|
37
|
-
"@ossy/themes": "^1.
|
|
30
|
+
"@ossy/connected-components": "^1.11.1",
|
|
31
|
+
"@ossy/design-system": "^1.11.1",
|
|
32
|
+
"@ossy/pages": "^1.11.1",
|
|
33
|
+
"@ossy/router": "^1.11.1",
|
|
34
|
+
"@ossy/router-react": "^1.11.1",
|
|
35
|
+
"@ossy/sdk": "^1.11.1",
|
|
36
|
+
"@ossy/sdk-react": "^1.11.1",
|
|
37
|
+
"@ossy/themes": "^1.11.1",
|
|
38
38
|
"@rollup/plugin-alias": "^6.0.0",
|
|
39
39
|
"@rollup/plugin-babel": "6.1.0",
|
|
40
40
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"README.md",
|
|
68
68
|
"tsconfig.json"
|
|
69
69
|
],
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "dfa200a3ea12c726db2054a0ab902844507716a0"
|
|
71
71
|
}
|