@ossy/app 1.10.0 → 1.11.0
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 +210 -0
- package/cli/build.js +29 -14
- package/cli/dev.js +19 -5
- package/cli/prerender-react.task.js +67 -40
- package/package.json +10 -10
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
2
|
+
|
|
3
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`
|
|
4
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`
|
|
5
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`
|
|
6
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`
|
|
7
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`
|
|
8
|
+
|
|
9
|
+
function stripAnsi (s) {
|
|
10
|
+
return String(s).replace(/\x1b\[[0-9;]*m/g, '')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function padVisible (s, width) {
|
|
14
|
+
const n = stripAnsi(s).length
|
|
15
|
+
return n >= width ? s : s + ' '.repeat(width - n)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function pageIdFromHydrateEntryName (entryName) {
|
|
19
|
+
const p = String(entryName)
|
|
20
|
+
return p.startsWith('hydrate__') ? p.slice('hydrate__'.length) : p
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fmtPart (part, shortLabel, frame) {
|
|
24
|
+
if (part.s === 'idle') return dim('—')
|
|
25
|
+
if (part.s === 'running') {
|
|
26
|
+
const sp = SPINNER[frame % SPINNER.length]
|
|
27
|
+
return `${yellow(sp)} ${dim(shortLabel + '…')}`
|
|
28
|
+
}
|
|
29
|
+
if (part.s === 'ok') return `${green('✔')} ${dim(`${part.ms}ms`)}`
|
|
30
|
+
if (part.s === 'fail') return `${red('✖')} ${dim(shortLabel)}`
|
|
31
|
+
if (part.s === 'skip') return dim(part.note ? `— ${part.note}` : '—')
|
|
32
|
+
return dim('—')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function rowLeadIcon (r, mode) {
|
|
36
|
+
if (mode === 'prerender-only') {
|
|
37
|
+
const p = r.prerender.s
|
|
38
|
+
if (p === 'fail') return red('✖')
|
|
39
|
+
if (p === 'running') return yellow('◐')
|
|
40
|
+
if (p === 'ok' || p === 'skip') return green('✔')
|
|
41
|
+
if (p === 'idle') return dim('·')
|
|
42
|
+
return green('✔')
|
|
43
|
+
}
|
|
44
|
+
const b = r.bundle.s
|
|
45
|
+
const p = r.prerender.s
|
|
46
|
+
if (b === 'fail' || p === 'fail') return red('✖')
|
|
47
|
+
if (b === 'running' || p === 'running') return yellow('◐')
|
|
48
|
+
if (b === 'ok' && p === 'idle') return yellow('◐')
|
|
49
|
+
if (b === 'ok' && (p === 'ok' || p === 'skip')) return green('✔')
|
|
50
|
+
if (b === 'idle' && p === 'idle') return dim('·')
|
|
51
|
+
return green('✔')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Lerna-style live table: one row per page, hydrate + prerender columns.
|
|
56
|
+
* TTY: redraws in place with a spinner while work runs. Non-TTY: one line per finished step.
|
|
57
|
+
*/
|
|
58
|
+
export function createParallelPagesReporter ({
|
|
59
|
+
scope = '@ossy/app',
|
|
60
|
+
pageIds,
|
|
61
|
+
stream = process.stdout,
|
|
62
|
+
/** `'full'`: hydrate + prerender columns. `'prerender-only'`: dev watch (client built separately). */
|
|
63
|
+
mode = 'full',
|
|
64
|
+
} = {}) {
|
|
65
|
+
const ids = [...pageIds].sort()
|
|
66
|
+
const maxId = Math.max(8, ...ids.map((id) => String(id).length))
|
|
67
|
+
const tty =
|
|
68
|
+
stream.isTTY === true &&
|
|
69
|
+
process.env.TERM !== 'dumb' &&
|
|
70
|
+
process.env.CI !== 'true' &&
|
|
71
|
+
process.env.OSSY_PLAIN_OUTPUT !== '1'
|
|
72
|
+
|
|
73
|
+
/** @type {Map<string, { bundle: object, prerender: object }>} */
|
|
74
|
+
const rows = new Map()
|
|
75
|
+
for (const id of ids) {
|
|
76
|
+
rows.set(id, {
|
|
77
|
+
bundle: { s: 'idle' },
|
|
78
|
+
prerender: { s: 'idle' },
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let frame = 0
|
|
83
|
+
let spinTimer = null
|
|
84
|
+
let blockLines = 0
|
|
85
|
+
|
|
86
|
+
const anyRunning = () => {
|
|
87
|
+
for (const r of rows.values()) {
|
|
88
|
+
if (r.bundle.s === 'running' || r.prerender.s === 'running') return true
|
|
89
|
+
}
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function ensureSpin () {
|
|
94
|
+
if (!tty || spinTimer) return
|
|
95
|
+
spinTimer = setInterval(() => {
|
|
96
|
+
frame += 1
|
|
97
|
+
redraw()
|
|
98
|
+
}, 80)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stopSpin () {
|
|
102
|
+
if (spinTimer) {
|
|
103
|
+
clearInterval(spinTimer)
|
|
104
|
+
spinTimer = null
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function lineFor (id) {
|
|
109
|
+
const r = rows.get(id)
|
|
110
|
+
const lead = rowLeadIcon(r, mode)
|
|
111
|
+
const idCol = padVisible(dim(String(id)), maxId)
|
|
112
|
+
const p = fmtPart(r.prerender, 'html', frame)
|
|
113
|
+
if (mode === 'prerender-only') {
|
|
114
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${p}`
|
|
115
|
+
}
|
|
116
|
+
const b = fmtPart(r.bundle, 'hydrate', frame)
|
|
117
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${padVisible(b, 24)} ${p}`
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function redraw () {
|
|
121
|
+
if (!tty) return
|
|
122
|
+
const lines = ids.map((id) => lineFor(id))
|
|
123
|
+
if (blockLines === 0) {
|
|
124
|
+
for (const ln of lines) stream.write(`${ln}\n`)
|
|
125
|
+
blockLines = lines.length
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
stream.write(`\x1b[${blockLines}A`)
|
|
129
|
+
for (const ln of lines) {
|
|
130
|
+
stream.write(`\x1b[2K\r${ln}\n`)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function nonTtyLine (id, phase, ok, ms, err) {
|
|
135
|
+
const label = phase === 'bundle' ? 'hydrate' : 'prerender'
|
|
136
|
+
const icon = ok ? green('✔') : red('✖')
|
|
137
|
+
const time = ms != null ? dim(` (${ms}ms)`) : ''
|
|
138
|
+
stream.write(`${icon} ${dim(`${scope}:${label}:`)}${id}${time}\n`)
|
|
139
|
+
if (err && !ok) stream.write(` ${red(String(err.message || err))}\n`)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
startBundle (pageId) {
|
|
144
|
+
if (mode === 'prerender-only') return
|
|
145
|
+
const r = rows.get(pageId)
|
|
146
|
+
if (!r) return
|
|
147
|
+
r.bundle = { s: 'running' }
|
|
148
|
+
ensureSpin()
|
|
149
|
+
redraw()
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
completeBundle (pageId, { ok, ms, error }) {
|
|
153
|
+
if (mode === 'prerender-only') return
|
|
154
|
+
const r = rows.get(pageId)
|
|
155
|
+
if (!r) return
|
|
156
|
+
r.bundle = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
157
|
+
if (!ok) {
|
|
158
|
+
r.prerender = { s: 'skip', note: 'bundle failed' }
|
|
159
|
+
if (!tty) nonTtyLine(pageId, 'bundle', false, ms, error)
|
|
160
|
+
}
|
|
161
|
+
if (!anyRunning()) stopSpin()
|
|
162
|
+
redraw()
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
startPrerender (pageId) {
|
|
166
|
+
const r = rows.get(pageId)
|
|
167
|
+
if (!r || r.prerender.s === 'skip') return
|
|
168
|
+
r.prerender = { s: 'running' }
|
|
169
|
+
ensureSpin()
|
|
170
|
+
redraw()
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
completePrerender (pageId, { ok, ms, error }) {
|
|
174
|
+
const r = rows.get(pageId)
|
|
175
|
+
if (!r || r.prerender.s === 'skip') return
|
|
176
|
+
r.prerender = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
177
|
+
if (!tty) nonTtyLine(pageId, 'prerender', ok, ms, error)
|
|
178
|
+
if (!anyRunning()) stopSpin()
|
|
179
|
+
redraw()
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
skipPrerender (pageId, note) {
|
|
183
|
+
const r = rows.get(pageId)
|
|
184
|
+
if (!r) return
|
|
185
|
+
if (r.bundle.s === 'fail') return
|
|
186
|
+
r.prerender = { s: 'skip', note: note || 'skipped' }
|
|
187
|
+
if (!tty) stream.write(`${dim('—')} ${scope}:prerender:${pageId} (${note})\n`)
|
|
188
|
+
redraw()
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
/** Stop spinner and leave cursor below the block (TTY). */
|
|
192
|
+
dispose () {
|
|
193
|
+
stopSpin()
|
|
194
|
+
if (tty && blockLines > 0) {
|
|
195
|
+
redraw()
|
|
196
|
+
stream.write('\n')
|
|
197
|
+
blockLines = 0
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
printSectionTitle (title) {
|
|
202
|
+
stopSpin()
|
|
203
|
+
if (tty && blockLines > 0) {
|
|
204
|
+
stream.write('\n')
|
|
205
|
+
blockLines = 0
|
|
206
|
+
}
|
|
207
|
+
stream.write(`\n ${bold(scope)} ${dim(title)}\n`)
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
}
|
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 { createParallelPagesReporter } 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)$/
|
|
@@ -600,7 +601,8 @@ export const build = async (cliArgs) => {
|
|
|
600
601
|
'-c': '--config',
|
|
601
602
|
}, { argv: cliArgs })
|
|
602
603
|
|
|
603
|
-
console.log('[@ossy/app
|
|
604
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild\x1b[0m')
|
|
605
|
+
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
604
606
|
|
|
605
607
|
|
|
606
608
|
const scriptDir = path.dirname(url.fileURLToPath(import.meta.url))
|
|
@@ -678,19 +680,32 @@ export const build = async (cliArgs) => {
|
|
|
678
680
|
copyOssyAppRuntime({ scriptDir, buildPath })
|
|
679
681
|
|
|
680
682
|
if (Object.keys(clientHydrateInput).length > 0) {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
683
|
+
const pageIds = [
|
|
684
|
+
...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir))),
|
|
685
|
+
].sort()
|
|
686
|
+
const reporter = pageIds.length
|
|
687
|
+
? createParallelPagesReporter({ pageIds })
|
|
688
|
+
: null
|
|
689
|
+
reporter?.printSectionTitle('client hydrate + prerender (parallel)')
|
|
690
|
+
try {
|
|
691
|
+
await prerenderReactTask.handler({
|
|
692
|
+
op: 'runProduction',
|
|
693
|
+
clientHydrateInput,
|
|
694
|
+
pageFilesLength: pageFiles.length,
|
|
695
|
+
copyPublicFrom: publicDir,
|
|
696
|
+
buildPath,
|
|
697
|
+
nodeEnv: 'production',
|
|
698
|
+
pagesBundlePath,
|
|
699
|
+
configSourcePath,
|
|
700
|
+
createClientRollupPlugins: createOssyClientRollupPlugins,
|
|
701
|
+
minifyBrowserStaticChunks,
|
|
702
|
+
reporter,
|
|
703
|
+
})
|
|
704
|
+
} finally {
|
|
705
|
+
reporter?.dispose()
|
|
706
|
+
}
|
|
693
707
|
}
|
|
694
708
|
|
|
695
|
-
console.log('[
|
|
709
|
+
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
710
|
+
console.log(' \x1b[32m✔\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild finished\x1b[0m\n')
|
|
696
711
|
};
|
package/cli/dev.js
CHANGED
|
@@ -29,13 +29,15 @@ import {
|
|
|
29
29
|
OSSY_RESOURCE_TEMPLATES_OUT,
|
|
30
30
|
} from './build.js';
|
|
31
31
|
import prerenderReactTask from './prerender-react.task.js'
|
|
32
|
+
import { createParallelPagesReporter } from './build-terminal.js'
|
|
32
33
|
import { watch } from 'rollup';
|
|
33
34
|
import arg from 'arg'
|
|
34
35
|
import { spawn } from 'node:child_process'
|
|
35
36
|
// import inject from '@rollup/plugin-inject'
|
|
36
37
|
|
|
37
38
|
export const dev = async (cliArgs) => {
|
|
38
|
-
console.log('[@ossy/app
|
|
39
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mdev\x1b[0m')
|
|
40
|
+
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
39
41
|
|
|
40
42
|
const options = arg({
|
|
41
43
|
'--config': String,
|
|
@@ -225,13 +227,15 @@ export const dev = async (cliArgs) => {
|
|
|
225
227
|
|
|
226
228
|
watcher.on('event', async (event) => {
|
|
227
229
|
if (event.code === 'BUNDLE_START') {
|
|
228
|
-
console.log('[@ossy/app
|
|
230
|
+
console.log(' \x1b[2m◐\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mrollup watch …\x1b[0m')
|
|
229
231
|
}
|
|
230
232
|
if (event.code === 'ERROR') {
|
|
231
|
-
console.error('[@ossy/app
|
|
233
|
+
console.error(' \x1b[31m✖\x1b[0m \x1b[1m@ossy/app\x1b[0m build error', event.error)
|
|
232
234
|
}
|
|
233
235
|
if (event.code === 'BUNDLE_END') {
|
|
234
|
-
console.log(
|
|
236
|
+
console.log(
|
|
237
|
+
` \x1b[32m✔\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mbundles\x1b[0m \x1b[2m(${event.duration}ms)\x1b[0m`
|
|
238
|
+
)
|
|
235
239
|
}
|
|
236
240
|
if (event.code === 'END') {
|
|
237
241
|
writeAppRuntimeShims({
|
|
@@ -240,15 +244,25 @@ export const dev = async (cliArgs) => {
|
|
|
240
244
|
})
|
|
241
245
|
copyOssyAppRuntime({ scriptDir, buildPath })
|
|
242
246
|
if (pageFiles.length > 0) {
|
|
247
|
+
const pageIds = [
|
|
248
|
+
...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir))),
|
|
249
|
+
].sort()
|
|
250
|
+
const reporter = pageIds.length
|
|
251
|
+
? createParallelPagesReporter({ pageIds, mode: 'prerender-only' })
|
|
252
|
+
: null
|
|
253
|
+
reporter?.printSectionTitle('prerender (parallel)')
|
|
243
254
|
try {
|
|
244
255
|
await prerenderReactTask.handler({
|
|
245
256
|
op: 'prerenderPagesParallel',
|
|
246
257
|
pagesBundlePath,
|
|
247
258
|
configSourcePath,
|
|
248
259
|
publicDir: path.join(buildPath, 'public'),
|
|
260
|
+
reporter,
|
|
249
261
|
})
|
|
250
262
|
} catch (err) {
|
|
251
|
-
console.error('[@ossy/app
|
|
263
|
+
console.error(' \x1b[31m✖\x1b[0m \x1b[1m@ossy/app\x1b[0m prerender failed', err)
|
|
264
|
+
} finally {
|
|
265
|
+
reporter?.dispose()
|
|
252
266
|
}
|
|
253
267
|
}
|
|
254
268
|
scheduleRestart()
|
|
@@ -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.0",
|
|
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.0",
|
|
31
|
+
"@ossy/design-system": "^1.11.0",
|
|
32
|
+
"@ossy/pages": "^1.11.0",
|
|
33
|
+
"@ossy/router": "^1.11.0",
|
|
34
|
+
"@ossy/router-react": "^1.11.0",
|
|
35
|
+
"@ossy/sdk": "^1.11.0",
|
|
36
|
+
"@ossy/sdk-react": "^1.11.0",
|
|
37
|
+
"@ossy/themes": "^1.11.0",
|
|
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": "a151faf7a9af599b885ea98137575978fa1dffae"
|
|
71
71
|
}
|