vike 0.4.152-commit-6f928f9 → 0.4.153-commit-159c659

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.
Files changed (63) hide show
  1. package/dist/cjs/node/cli/bin.js +2 -2
  2. package/dist/cjs/node/plugin/index.js +2 -2
  3. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
  4. package/dist/cjs/node/plugin/plugins/envVars.js +1 -1
  5. package/dist/cjs/node/plugin/plugins/{assertFileEnv.js → fileEnv.js} +4 -4
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -9
  7. package/dist/cjs/node/prerender/index.js +1 -1
  8. package/dist/cjs/node/prerender/runPrerender.js +21 -13
  9. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +5 -3
  10. package/dist/cjs/node/runtime/renderPage/{loadPageFilesServerSide.js → loadUserFilesServerSide.js} +5 -5
  11. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -4
  12. package/dist/cjs/node/runtime/renderPage.js +2 -2
  13. package/dist/cjs/shared/hooks/getHook.js +14 -8
  14. package/dist/cjs/shared/misc/isRenderFailure.js +4 -0
  15. package/dist/cjs/shared/misc/pageContextInitIsPassedToClient.js +4 -0
  16. package/dist/cjs/shared/route/abort.js +15 -4
  17. package/dist/cjs/shared/route/loadPageRoutes.js +1 -9
  18. package/dist/cjs/utils/projectInfo.js +1 -1
  19. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +27 -32
  20. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +39 -55
  21. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +1 -1
  22. package/dist/esm/client/client-routing-runtime/installClientRouter.js +8 -2
  23. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +2 -2
  24. package/dist/esm/client/client-routing-runtime/onLinkClick.js +2 -2
  25. package/dist/esm/client/client-routing-runtime/prefetch.js +2 -2
  26. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +209 -141
  27. package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +2 -2
  28. package/dist/esm/client/server-routing-runtime/getPageContext.js +5 -4
  29. package/dist/esm/client/shared/getPageContextSerializedInHtml.d.ts +0 -1
  30. package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -4
  31. package/dist/esm/client/shared/{loadPageFilesClientSide.d.ts → loadUserFilesClientSide.d.ts} +7 -6
  32. package/dist/esm/client/shared/{loadPageFilesClientSide.js → loadUserFilesClientSide.js} +4 -4
  33. package/dist/esm/node/cli/bin.js +3 -3
  34. package/dist/esm/node/plugin/index.js +2 -2
  35. package/dist/esm/node/plugin/plugins/autoFullBuild.js +3 -3
  36. package/dist/esm/node/plugin/plugins/envVars.js +1 -1
  37. package/dist/esm/node/plugin/plugins/fileEnv.d.ts +3 -0
  38. package/dist/esm/node/plugin/plugins/{assertFileEnv.js → fileEnv.js} +3 -3
  39. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -9
  40. package/dist/esm/node/prerender/index.d.ts +1 -1
  41. package/dist/esm/node/prerender/index.js +1 -1
  42. package/dist/esm/node/prerender/runPrerender.d.ts +8 -8
  43. package/dist/esm/node/prerender/runPrerender.js +22 -14
  44. package/dist/esm/node/runtime/html/serializePageContextClientSide.d.ts +0 -1
  45. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +5 -3
  46. package/dist/esm/node/runtime/renderPage/{loadPageFilesServerSide.d.ts → loadUserFilesServerSide.d.ts} +6 -6
  47. package/dist/esm/node/runtime/renderPage/{loadPageFilesServerSide.js → loadUserFilesServerSide.js} +4 -4
  48. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +2 -2
  49. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -4
  50. package/dist/esm/node/runtime/renderPage.js +2 -2
  51. package/dist/esm/shared/hooks/getHook.d.ts +2 -0
  52. package/dist/esm/shared/hooks/getHook.js +13 -7
  53. package/dist/esm/shared/misc/isRenderFailure.d.ts +1 -0
  54. package/dist/esm/shared/misc/isRenderFailure.js +1 -0
  55. package/dist/esm/shared/misc/pageContextInitIsPassedToClient.d.ts +1 -0
  56. package/dist/esm/shared/misc/pageContextInitIsPassedToClient.js +1 -0
  57. package/dist/esm/shared/route/abort.d.ts +1 -1
  58. package/dist/esm/shared/route/abort.js +16 -5
  59. package/dist/esm/shared/route/loadPageRoutes.js +1 -9
  60. package/dist/esm/utils/projectInfo.d.ts +2 -2
  61. package/dist/esm/utils/projectInfo.js +1 -1
  62. package/package.json +1 -1
  63. package/dist/esm/node/plugin/plugins/assertFileEnv.d.ts +0 -3
@@ -2,13 +2,13 @@ export { renderPageClientSide };
2
2
  export { getRenderCount };
3
3
  export { disableClientRouting };
4
4
  import { assert, getCurrentUrl, isSameErrorMessage, objectAssign, serverSideRouteTo, getGlobalObject, executeHook, hasProp } from './utils.js';
5
- import { getPageContextFromHooks_errorPage, getPageContextFromHooks_firstRender, getPageContextFromHooks_uponNavigation, isServerSideRouted } from './getPageContextFromHooks.js';
5
+ import { getPageContextFromHooks_isHydration, getPageContextFromHooks_isNotHydration, getPageContextFromHooks_serialized, isServerSideRouted } from './getPageContextFromHooks.js';
6
6
  import { createPageContext } from './createPageContext.js';
7
7
  import { addLinkPrefetchHandlers } from './prefetch.js';
8
8
  import { assertInfo, assertWarning, isReact } from './utils.js';
9
9
  import { executeOnRenderClientHook } from '../shared/executeOnRenderClientHook.js';
10
10
  import { assertHook, getHook } from '../../shared/hooks/getHook.js';
11
- import { isErrorFetchingStaticAssets } from '../shared/loadPageFilesClientSide.js';
11
+ import { isErrorFetchingStaticAssets, loadUserFilesClientSide } from '../shared/loadUserFilesClientSide.js';
12
12
  import { pushHistory } from './history.js';
13
13
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
14
14
  import { route } from '../../shared/route/index.js';
@@ -16,12 +16,14 @@ import { isClientSideRoutable } from './isClientSideRoutable.js';
16
16
  import { setScrollPosition } from './setScrollPosition.js';
17
17
  import { updateState } from './onBrowserHistoryNavigation.js';
18
18
  import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
19
+ import { getErrorPageId } from '../../shared/error-page.js';
20
+ import { isRenderFailure } from '../../shared/misc/isRenderFailure.js';
19
21
  const globalObject = getGlobalObject('renderPageClientSide.ts', { renderCounter: 0 });
20
22
  async function renderPageClientSide(renderArgs) {
21
23
  const { scrollTarget, urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
22
- const { isRenderOutdated, setHydrationCanBeAborted, isFirstRender } = getIsRenderOutdated();
23
- const callTransitionHooks = !isFirstRender;
24
- assert(isClientSideNavigation === !isFirstRender);
24
+ // isHydrationRender <=> the first render attempt
25
+ const { isRenderOutdated, setHydrationCanBeAborted, isHydrationRender } = getIsRenderOutdated();
26
+ assert(isClientSideNavigation === !isHydrationRender);
25
27
  assertNoInfiniteAbortLoop(pageContextsFromRewrite.length, redirectCount);
26
28
  if (globalObject.clientRoutingIsDisabled) {
27
29
  serverSideRouteTo(urlOriginal);
@@ -33,92 +35,130 @@ async function renderPageClientSide(renderArgs) {
33
35
  const pageContext = await getPageContextBegin();
34
36
  if (isRenderOutdated())
35
37
  return;
36
- let renderState = {};
37
- if (!isFirstRender) {
38
- // Route
38
+ // Route
39
+ let pageContextRouted;
40
+ if (isHydrationRender) {
41
+ const pageContextSerialized = getPageContextFromHooks_serialized();
42
+ pageContextRouted = pageContextSerialized;
43
+ }
44
+ else {
45
+ let pageContextFromRoute;
39
46
  try {
40
- renderState = { pageContextFromRoute: await route(pageContext) };
47
+ pageContextFromRoute = await route(pageContext);
41
48
  }
42
49
  catch (err) {
43
- await renderErrorPage(err);
50
+ await renderErrorPage({ err });
44
51
  return;
45
52
  }
46
53
  if (isRenderOutdated())
47
54
  return;
48
- // Check whether rendering should be skipped
49
- if (renderState.pageContextFromRoute) {
50
- const { pageContextFromRoute } = renderState;
51
- assert(!('urlOriginal' in pageContextFromRoute));
52
- objectAssign(pageContext, pageContextFromRoute);
53
- let isClientRoutable;
54
- if (!pageContextFromRoute._pageId) {
55
- isClientRoutable = false;
56
- }
57
- else {
58
- isClientRoutable = await isClientSideRoutable(pageContextFromRoute._pageId, pageContext);
59
- if (isRenderOutdated())
60
- return;
61
- }
62
- if (!isClientRoutable) {
63
- serverSideRouteTo(urlOriginal);
64
- return;
65
- }
66
- const isSamePage = pageContextFromRoute._pageId &&
67
- globalObject.previousPageContext?._pageId &&
68
- pageContextFromRoute._pageId === globalObject.previousPageContext._pageId;
69
- if (isUserLandPushStateNavigation && isSamePage) {
70
- // Skip's Vike's rendering; let the user handle the navigation
55
+ let isClientRoutable;
56
+ if (!pageContextFromRoute._pageId) {
57
+ isClientRoutable = false;
58
+ }
59
+ else {
60
+ isClientRoutable = await isClientSideRoutable(pageContextFromRoute._pageId, pageContext);
61
+ if (isRenderOutdated())
71
62
  return;
72
- }
63
+ }
64
+ if (!isClientRoutable) {
65
+ serverSideRouteTo(urlOriginal);
66
+ return;
67
+ }
68
+ assert(hasProp(pageContextFromRoute, '_pageId', 'string')); // Help TS
69
+ const isSamePage = pageContextFromRoute._pageId &&
70
+ globalObject.previousPageContext?._pageId &&
71
+ pageContextFromRoute._pageId === globalObject.previousPageContext._pageId;
72
+ if (isUserLandPushStateNavigation && isSamePage) {
73
+ // Skip's Vike's rendering; let the user handle the navigation
74
+ return;
75
+ }
76
+ pageContextRouted = pageContextFromRoute;
77
+ }
78
+ assert(!('urlOriginal' in pageContextRouted));
79
+ objectAssign(pageContext, pageContextRouted);
80
+ try {
81
+ objectAssign(pageContext, await loadUserFilesClientSide(pageContext._pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
82
+ }
83
+ catch (err) {
84
+ if (handleErrorFetchingStaticAssets(err, pageContext, isHydrationRender)) {
85
+ return;
86
+ }
87
+ else {
88
+ throw err;
73
89
  }
74
90
  }
91
+ if (isRenderOutdated())
92
+ return;
93
+ // Set global hydrationCanBeAborted
94
+ if (pageContext.exports.hydrationCanBeAborted) {
95
+ setHydrationCanBeAborted();
96
+ }
97
+ else {
98
+ assertWarning(!isReact(), 'You seem to be using React; we recommend setting hydrationCanBeAborted to true, see https://vike.dev/hydrationCanBeAborted', { onlyOnce: true });
99
+ }
100
+ // There wasn't any `await` but result may change because we just called setHydrationCanBeAborted()
101
+ if (isRenderOutdated())
102
+ return;
75
103
  // onPageTransitionStart()
76
- if (callTransitionHooks) {
104
+ if (!isHydrationRender) {
105
+ assertHook(pageContext, 'onPageTransitionStart');
77
106
  if (!globalObject.isTransitioning) {
78
- if (globalObject.onPageTransitionStart) {
79
- const hook = globalObject.onPageTransitionStart;
107
+ globalObject.isTransitioning = true;
108
+ const onPageTransitionStartHook = getHook(pageContext, 'onPageTransitionStart');
109
+ if (onPageTransitionStartHook) {
110
+ const hook = onPageTransitionStartHook;
80
111
  const { hookFn } = hook;
81
- await executeHook(() => hookFn(pageContext), hook);
112
+ try {
113
+ await executeHook(() => hookFn(pageContext), hook);
114
+ }
115
+ catch (err) {
116
+ await renderErrorPage({ err });
117
+ return;
118
+ }
119
+ if (isRenderOutdated())
120
+ return;
82
121
  }
83
- globalObject.isTransitioning = true;
84
- if (isRenderOutdated())
85
- return;
86
122
  }
87
123
  }
88
- if (isFirstRender) {
89
- assert(!renderState.pageContextFromRoute);
124
+ // Get pageContext from hooks (fetched from server, and/or directly called on the client-side)
125
+ if (isHydrationRender) {
126
+ assert(hasProp(pageContext, '_hasPageContextFromServer', 'true'));
127
+ let pageContextFromHooks;
90
128
  try {
91
- renderState.pageContextFromHooks = await getPageContextFromHooks_firstRender(pageContext);
129
+ pageContextFromHooks = await getPageContextFromHooks_isHydration(pageContext);
92
130
  }
93
131
  catch (err) {
94
- await renderErrorPage(err);
132
+ await renderErrorPage({ err });
95
133
  return;
96
134
  }
97
135
  if (isRenderOutdated())
98
136
  return;
137
+ assert(!('urlOriginal' in pageContextFromHooks));
138
+ objectAssign(pageContext, pageContextFromHooks);
139
+ // Render page view
140
+ await renderPageView(pageContext);
99
141
  }
100
142
  else {
101
- const { pageContextFromRoute } = renderState;
102
- assert(pageContextFromRoute);
103
- assert(pageContextFromRoute._pageId);
104
- assert(hasProp(pageContextFromRoute, '_pageId', 'string')); // Help TS
105
- assert(!('urlOriginal' in pageContextFromRoute));
106
- objectAssign(pageContext, pageContextFromRoute);
143
+ let pageContextFromHooks;
107
144
  try {
108
- renderState.pageContextFromHooks = await getPageContextFromHooks_uponNavigation(pageContext);
145
+ pageContextFromHooks = await getPageContextFromHooks_isNotHydration(pageContext, false);
109
146
  }
110
147
  catch (err) {
111
- await renderErrorPage(err);
148
+ await renderErrorPage({ err });
112
149
  return;
113
150
  }
114
151
  if (isRenderOutdated())
115
152
  return;
153
+ if (isRenderFailure in pageContextFromHooks) {
154
+ await renderErrorPage({ pageContextError: pageContextFromHooks });
155
+ return;
156
+ }
157
+ assert(!('urlOriginal' in pageContextFromHooks));
158
+ objectAssign(pageContext, pageContextFromHooks);
159
+ // Render page view
160
+ await renderPageView(pageContext);
116
161
  }
117
- const { pageContextFromHooks } = renderState;
118
- assert(pageContextFromHooks);
119
- assert(!('urlOriginal' in pageContextFromHooks));
120
- objectAssign(pageContext, pageContextFromHooks);
121
- await renderPageView(pageContext);
122
162
  }
123
163
  async function getPageContextBegin() {
124
164
  const pageContext = await createPageContext(urlOriginal);
@@ -133,88 +173,112 @@ async function renderPageClientSide(renderArgs) {
133
173
  }
134
174
  return pageContext;
135
175
  }
136
- async function renderErrorPage(err) {
176
+ async function renderErrorPage(args) {
137
177
  const pageContext = await getPageContextBegin();
138
178
  if (isRenderOutdated())
139
179
  return;
140
- assert(err);
141
- assert(!('errorWhileRendering' in pageContext));
142
- pageContext.errorWhileRendering = err;
143
- if (!isAbortError(err)) {
144
- // We don't swallow 404 errors:
145
- // - On the server-side, Vike swallows / doesn't show any 404 error log because it's expected that a user may go to some random non-existent URL. (We don't want to flood the app's error tracking with 404 logs.)
146
- // - On the client-side, if the user navigates to a 404 then it means that the UI has a broken link. (It isn't expected that users can go to some random URL using the client-side router, as it would require, for example, the user to manually change the URL of a link by manually manipulating the DOM which highly unlikely.)
147
- console.error(err);
148
- }
149
- else {
150
- // We swallow throw redirect()/render() called by client-side hooks onBeforeRender()/data()/guard()
151
- // We handle the abort error down below.
180
+ if (args.pageContextError) {
181
+ objectAssign(pageContext, args.pageContextError);
152
182
  }
153
- if (shouldSwallowAndInterrupt(err, pageContext, isFirstRender))
154
- return;
155
- if (isAbortError(err)) {
156
- const errAbort = err;
157
- logAbortErrorHandled(err, !import.meta.env.DEV, pageContext);
158
- const pageContextAbort = errAbort._pageContextAbort;
159
- // throw render('/some-url')
160
- if (pageContextAbort._urlRewrite) {
161
- await renderPageClientSide({
162
- ...renderArgs,
163
- scrollTarget: 'scroll-to-top-or-hash',
164
- pageContextsFromRewrite: [...pageContextsFromRewrite, pageContextAbort]
165
- });
183
+ if ('err' in args) {
184
+ const { err } = args;
185
+ assert(err);
186
+ assert(!('errorWhileRendering' in pageContext));
187
+ pageContext.errorWhileRendering = err;
188
+ if (shouldSwallowAndInterrupt(err))
166
189
  return;
190
+ if (!isAbortError(err)) {
191
+ // We don't swallow 404 errors:
192
+ // - On the server-side, Vike swallows / doesn't show any 404 error log because it's expected that a user may go to some random non-existent URL. (We don't want to flood the app's error tracking with 404 logs.)
193
+ // - On the client-side, if the user navigates to a 404 then it means that the UI has a broken link. (It isn't expected that users can go to some random URL using the client-side router, as it would require, for example, the user to manually change the URL of a link by manually manipulating the DOM which highly unlikely.)
194
+ console.error(err);
167
195
  }
168
- // throw redirect('/some-url')
169
- if (pageContextAbort._urlRedirect) {
170
- const urlRedirect = pageContextAbort._urlRedirect.url;
171
- if (urlRedirect.startsWith('http')) {
172
- // External redirection
173
- window.location.href = urlRedirect;
174
- return;
175
- }
176
- else {
196
+ else {
197
+ // We swallow throw redirect()/render() called by client-side hooks onBeforeRender()/data()/guard()
198
+ // We handle the abort error down below.
199
+ }
200
+ if (isAbortError(err)) {
201
+ const errAbort = err;
202
+ logAbortErrorHandled(err, !import.meta.env.DEV, pageContext);
203
+ const pageContextAbort = errAbort._pageContextAbort;
204
+ // throw render('/some-url')
205
+ if (pageContextAbort._urlRewrite) {
177
206
  await renderPageClientSide({
178
207
  ...renderArgs,
179
208
  scrollTarget: 'scroll-to-top-or-hash',
180
- urlOriginal: urlRedirect,
181
- overwriteLastHistoryEntry: false,
182
- isBackwardNavigation: false,
183
- redirectCount: redirectCount + 1
209
+ pageContextsFromRewrite: [...pageContextsFromRewrite, pageContextAbort]
184
210
  });
211
+ return;
212
+ }
213
+ // throw redirect('/some-url')
214
+ if (pageContextAbort._urlRedirect) {
215
+ const urlRedirect = pageContextAbort._urlRedirect.url;
216
+ if (urlRedirect.startsWith('http')) {
217
+ // External redirection
218
+ window.location.href = urlRedirect;
219
+ return;
220
+ }
221
+ else {
222
+ await renderPageClientSide({
223
+ ...renderArgs,
224
+ scrollTarget: 'scroll-to-top-or-hash',
225
+ urlOriginal: urlRedirect,
226
+ overwriteLastHistoryEntry: false,
227
+ isBackwardNavigation: false,
228
+ redirectCount: redirectCount + 1
229
+ });
230
+ }
231
+ return;
232
+ }
233
+ // throw render(statusCode)
234
+ assert(pageContextAbort.abortStatusCode);
235
+ assert(!('urlOriginal' in pageContextAbort));
236
+ objectAssign(pageContext, pageContextAbort);
237
+ if (pageContextAbort.abortStatusCode === 404) {
238
+ objectAssign(pageContext, { is404: true });
185
239
  }
186
- return;
187
240
  }
188
- // throw render(statusCode)
189
- assert(pageContextAbort.abortStatusCode);
190
- assert(!('urlOriginal' in pageContextAbort));
191
- objectAssign(pageContext, pageContextAbort);
192
- if (pageContextAbort.abortStatusCode === 404) {
193
- objectAssign(pageContext, { is404: true });
241
+ else {
242
+ objectAssign(pageContext, { is404: false });
194
243
  }
195
244
  }
196
- else {
197
- objectAssign(pageContext, { is404: false });
245
+ const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
246
+ if (!errorPageId)
247
+ throw new Error('No error page defined.');
248
+ objectAssign(pageContext, {
249
+ _pageId: errorPageId
250
+ });
251
+ try {
252
+ objectAssign(pageContext, await loadUserFilesClientSide(pageContext._pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
253
+ }
254
+ catch (err) {
255
+ if (handleErrorFetchingStaticAssets(err, pageContext, isHydrationRender)) {
256
+ return;
257
+ }
258
+ else {
259
+ throw err;
260
+ }
198
261
  }
262
+ if (isRenderOutdated())
263
+ return;
199
264
  let pageContextFromHooks;
200
265
  try {
201
- pageContextFromHooks = await getPageContextFromHooks_errorPage(pageContext);
266
+ pageContextFromHooks = await getPageContextFromHooks_isNotHydration(pageContext, true);
202
267
  }
203
268
  catch (errErrorPage) {
204
269
  // - When user hasn't defined a `_error.page.js` file
205
270
  // - Some Vike unpexected internal error
206
- if (shouldSwallowAndInterrupt(errErrorPage, pageContext, isFirstRender))
271
+ if (shouldSwallowAndInterrupt(errErrorPage))
207
272
  return;
208
- if (isSameErrorMessage(err, errErrorPage)) {
273
+ if (!isSameErrorMessage(args.err, errErrorPage)) {
209
274
  /* When we can't render the error page, we prefer showing a blank page over letting the server-side try because otherwise:
210
275
  - We risk running into an infinite loop of reloads which would overload the server.
211
276
  - An infinite reloading page is a even worse UX than a blank page.
212
277
  serverSideRouteTo(urlOriginal)
213
278
  */
214
- return;
279
+ console.error(errErrorPage);
215
280
  }
216
- // We `throw err2` instead of `console.error(err2)` so that, when using `navigate()`, the error propagates to the user `navigate()` call
217
- throw errErrorPage;
281
+ return;
218
282
  }
219
283
  if (isRenderOutdated())
220
284
  return;
@@ -224,20 +288,6 @@ async function renderPageClientSide(renderArgs) {
224
288
  await renderPageView(pageContext, true);
225
289
  }
226
290
  async function renderPageView(pageContext, isErrorPage) {
227
- // Set global onPageTransitionStart()
228
- assertHook(pageContext, 'onPageTransitionStart');
229
- const onPageTransitionStartHook = getHook(pageContext, 'onPageTransitionStart');
230
- globalObject.onPageTransitionStart = onPageTransitionStartHook;
231
- // Set global hydrationCanBeAborted
232
- if (pageContext.exports.hydrationCanBeAborted) {
233
- setHydrationCanBeAborted();
234
- }
235
- else {
236
- assertWarning(!isReact(), 'You seem to be using React; we recommend setting hydrationCanBeAborted to true, see https://vike.dev/hydrationCanBeAborted', { onlyOnce: true });
237
- }
238
- // There wasn't any `await` but result may change because we just called setHydrationCanBeAborted()
239
- if (isRenderOutdated())
240
- return;
241
291
  // We use globalObject.renderPromise in order to ensure that there is never two concurrent onRenderClient() calls
242
292
  if (globalObject.renderPromise) {
243
293
  // Make sure that the previous render has finished
@@ -255,7 +305,7 @@ async function renderPageClientSide(renderArgs) {
255
305
  }
256
306
  catch (err) {
257
307
  if (!isErrorPage) {
258
- renderErrorPage(err);
308
+ renderErrorPage({ err });
259
309
  }
260
310
  else {
261
311
  throw err;
@@ -267,33 +317,53 @@ async function renderPageClientSide(renderArgs) {
267
317
  await globalObject.renderPromise;
268
318
  assert(globalObject.renderPromise === undefined);
269
319
  /* We don't abort in order to ensure that onHydrationEnd() is called: we abort only after onHydrationEnd() is called.
270
- if (isRenderOutdated(true)) return
271
- */
320
+ if (isRenderOutdated(true)) return
321
+ */
272
322
  // onHydrationEnd()
273
- if (isFirstRender) {
323
+ if (isHydrationRender) {
274
324
  assertHook(pageContext, 'onHydrationEnd');
275
325
  const hook = getHook(pageContext, 'onHydrationEnd');
276
326
  if (hook) {
277
327
  const { hookFn } = hook;
278
- await executeHook(() => hookFn(pageContext), hook);
328
+ try {
329
+ await executeHook(() => hookFn(pageContext), hook);
330
+ }
331
+ catch (err) {
332
+ if (!isErrorPage) {
333
+ renderErrorPage({ err });
334
+ }
335
+ else {
336
+ throw err;
337
+ }
338
+ }
279
339
  if (isRenderOutdated(true))
280
340
  return;
281
341
  }
282
342
  }
283
- // We abort only after onHydrationEnd() is called
343
+ // We abort *after* onHydrationEnd() is called
284
344
  if (isRenderOutdated(true))
285
345
  return;
286
346
  // onPageTransitionEnd()
287
- if (callTransitionHooks) {
347
+ if (globalObject.isTransitioning) {
348
+ globalObject.isTransitioning = undefined;
288
349
  assertHook(pageContext, 'onPageTransitionEnd');
289
350
  const hook = getHook(pageContext, 'onPageTransitionEnd');
290
351
  if (hook) {
291
352
  const { hookFn } = hook;
292
- await executeHook(() => hookFn(pageContext), hook);
353
+ try {
354
+ await executeHook(() => hookFn(pageContext), hook);
355
+ }
356
+ catch (err) {
357
+ if (!isErrorPage) {
358
+ renderErrorPage({ err });
359
+ }
360
+ else {
361
+ throw err;
362
+ }
363
+ }
293
364
  if (isRenderOutdated(true))
294
365
  return;
295
366
  }
296
- globalObject.isTransitioning = undefined;
297
367
  }
298
368
  // Page scrolling
299
369
  setScrollPosition(scrollTarget);
@@ -308,18 +378,16 @@ function changeUrl(url, overwriteLastHistoryEntry) {
308
378
  pushHistory(url, overwriteLastHistoryEntry);
309
379
  updateState();
310
380
  }
311
- function shouldSwallowAndInterrupt(err, pageContext, isFirstRender) {
381
+ function shouldSwallowAndInterrupt(err) {
312
382
  if (isServerSideRouted(err))
313
383
  return true;
314
- if (handleErrorFetchingStaticAssets(err, pageContext, isFirstRender))
315
- return true;
316
384
  return false;
317
385
  }
318
- function handleErrorFetchingStaticAssets(err, pageContext, isFirstRender) {
386
+ function handleErrorFetchingStaticAssets(err, pageContext, isHydrationRender) {
319
387
  if (!isErrorFetchingStaticAssets(err)) {
320
388
  return false;
321
389
  }
322
- if (isFirstRender) {
390
+ if (isHydrationRender) {
323
391
  disableClientRouting(err, false);
324
392
  // This may happen if the frontend was newly deployed during hydration.
325
393
  // Ideally: re-try a couple of times by reloading the page (not entirely trivial to implement since `localStorage` is needed.)
@@ -371,7 +439,7 @@ function getIsRenderOutdated() {
371
439
  return {
372
440
  isRenderOutdated,
373
441
  setHydrationCanBeAborted,
374
- isFirstRender: renderNumber === 1
442
+ isHydrationRender: renderNumber === 1
375
443
  };
376
444
  }
377
445
  function getRenderCount() {
@@ -1,11 +1,11 @@
1
1
  export { getPageContext };
2
2
  declare function getPageContext(): Promise<{
3
3
  _pageId: string;
4
- _hasPageContextFromServer: true;
5
4
  } & {
6
5
  isHydration: true;
7
6
  isBackwardNavigation: null;
8
- _hasPageContextFromClient: boolean;
7
+ _hasPageContextFromServer: true;
8
+ _hasPageContextFromClient: false;
9
9
  } & {
10
10
  _pageFilesAll: import("../../shared/getPageFiles/getPageFileObject.js").PageFile[];
11
11
  _pageConfigs: import("../../shared/page-configs/PageConfig.js").PageConfigRuntime[];
@@ -1,7 +1,7 @@
1
1
  import { assertUsage, assertWarning, getCurrentUrl, objectAssign } from './utils.js';
2
2
  import { getPageContextSerializedInHtml } from '../shared/getPageContextSerializedInHtml.js';
3
3
  import { getPageFilesAll } from '../../shared/getPageFiles.js';
4
- import { loadPageFilesClientSide } from '../shared/loadPageFilesClientSide.js';
4
+ import { loadUserFilesClientSide } from '../shared/loadUserFilesClientSide.js';
5
5
  export { getPageContext };
6
6
  const urlFirst = getCurrentUrl({ withoutHash: true });
7
7
  async function getPageContext() {
@@ -9,9 +9,10 @@ async function getPageContext() {
9
9
  objectAssign(pageContext, {
10
10
  isHydration: true,
11
11
  isBackwardNavigation: null,
12
+ _hasPageContextFromServer: true,
12
13
  _hasPageContextFromClient: false
13
14
  });
14
- objectAssign(pageContext, await loadPageFiles(pageContext._pageId));
15
+ objectAssign(pageContext, await loadPageUserFiles(pageContext._pageId));
15
16
  assertPristineUrl();
16
17
  return pageContext;
17
18
  }
@@ -19,14 +20,14 @@ function assertPristineUrl() {
19
20
  const urlCurrent = getCurrentUrl({ withoutHash: true });
20
21
  assertUsage(urlFirst === urlCurrent, `The URL was manipulated before the hydration finished ('${urlFirst}' to '${urlCurrent}'). Ensure the hydration has finished before manipulating the URL. Consider using the onHydrationEnd() hook.`);
21
22
  }
22
- async function loadPageFiles(pageId) {
23
+ async function loadPageUserFiles(pageId) {
23
24
  const pageContextAddendum = {};
24
25
  const { pageFilesAll, pageConfigs } = await getPageFilesAll(true);
25
26
  objectAssign(pageContextAddendum, {
26
27
  _pageFilesAll: pageFilesAll,
27
28
  _pageConfigs: pageConfigs
28
29
  });
29
- objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageId, pageContextAddendum));
30
+ objectAssign(pageContextAddendum, await loadUserFilesClientSide(pageId, pageContextAddendum._pageFilesAll, pageContextAddendum._pageConfigs));
30
31
  pageFilesAll
31
32
  .filter((p) => p.fileType !== '.page.server')
32
33
  .forEach((p) => {
@@ -1,5 +1,4 @@
1
1
  export { getPageContextSerializedInHtml };
2
2
  declare function getPageContextSerializedInHtml(): {
3
3
  _pageId: string;
4
- _hasPageContextFromServer: true;
5
4
  };
@@ -1,5 +1,5 @@
1
1
  import { parse } from '@brillout/json-serializer/parse';
2
- import { hasProp, assert, assertUsage, objectAssign } from '../server-routing-runtime/utils.js';
2
+ import { hasProp, assert, assertUsage } from '../server-routing-runtime/utils.js';
3
3
  export { getPageContextSerializedInHtml };
4
4
  function getPageContextSerializedInHtml() {
5
5
  // elem should exist because:
@@ -15,8 +15,5 @@ function getPageContextSerializedInHtml() {
15
15
  assert(pageContextJson);
16
16
  const pageContextSerializedInHtml = parse(pageContextJson);
17
17
  assert(hasProp(pageContextSerializedInHtml, '_pageId', 'string'));
18
- objectAssign(pageContextSerializedInHtml, {
19
- _hasPageContextFromServer: true
20
- });
21
18
  return pageContextSerializedInHtml;
22
19
  }
@@ -1,13 +1,14 @@
1
- export { loadPageFilesClientSide };
1
+ export { loadUserFilesClientSide };
2
2
  export { isErrorFetchingStaticAssets };
3
- export type { PageContextPageFiles };
3
+ export type { PageContextUserFiles };
4
4
  import { type PageFile, type PageContextExports } from '../../shared/getPageFiles.js';
5
5
  import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
6
- type PageContextPageFiles = {
6
+ type PageContextUserFilesLoaded = PageContextExports & {
7
+ _pageFilesLoaded: PageFile[];
8
+ };
9
+ type PageContextUserFiles = {
7
10
  _pageFilesAll: PageFile[];
8
11
  _pageConfigs: PageConfigRuntime[];
9
12
  };
10
- declare function loadPageFilesClientSide(pageId: string, pageContext: PageContextPageFiles): Promise<PageContextExports & {
11
- _pageFilesLoaded: PageFile[];
12
- }>;
13
+ declare function loadUserFilesClientSide(pageId: string, pageFilesAll: PageFile[], pageConfigs: PageConfigRuntime[]): Promise<PageContextUserFilesLoaded>;
13
14
  declare function isErrorFetchingStaticAssets(err: unknown): boolean;
@@ -1,12 +1,12 @@
1
- export { loadPageFilesClientSide };
1
+ export { loadUserFilesClientSide };
2
2
  export { isErrorFetchingStaticAssets };
3
3
  import { getPageFilesClientSide, getExports } from '../../shared/getPageFiles.js';
4
4
  import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
5
5
  import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
6
6
  const stamp = '__whileFetchingAssets';
7
- async function loadPageFilesClientSide(pageId, pageContext) {
8
- const pageFilesClientSide = getPageFilesClientSide(pageContext._pageFilesAll, pageId);
9
- const pageConfig = findPageConfig(pageContext._pageConfigs, pageId);
7
+ async function loadUserFilesClientSide(pageId, pageFilesAll, pageConfigs) {
8
+ const pageFilesClientSide = getPageFilesClientSide(pageFilesAll, pageId);
9
+ const pageConfig = findPageConfig(pageConfigs, pageId);
10
10
  let pageConfigLoaded;
11
11
  // @ts-ignore Since dist/cjs/client/ is never used, we can ignore this error.
12
12
  const isDev = import.meta.env.DEV;
@@ -1,6 +1,6 @@
1
1
  import { cac } from 'cac';
2
2
  import { resolve } from 'path';
3
- import { prerenderFromCLI, prerenderForceExit } from '../prerender/runPrerender.js';
3
+ import { runPrerenderFromCLI, runPrerender_forceExit } from '../prerender/runPrerender.js';
4
4
  import { projectInfo, assertUsage } from './utils.js';
5
5
  const cli = cac(projectInfo.projectName);
6
6
  cli
@@ -10,8 +10,8 @@ cli
10
10
  assertOptions();
11
11
  const { partial, noExtraDir, base, parallel, outDir, configFile } = options;
12
12
  const root = options.root && resolve(options.root);
13
- await prerenderFromCLI({ partial, noExtraDir, base, root, parallel, outDir, configFile });
14
- prerenderForceExit();
13
+ await runPrerenderFromCLI({ partial, noExtraDir, base, root, parallel, outDir, configFile });
14
+ runPrerender_forceExit();
15
15
  });
16
16
  function assertOptions() {
17
17
  // Using process.argv because cac convert names to camelCase