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.
- package/dist/cjs/node/cli/bin.js +2 -2
- package/dist/cjs/node/plugin/index.js +2 -2
- package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
- package/dist/cjs/node/plugin/plugins/envVars.js +1 -1
- package/dist/cjs/node/plugin/plugins/{assertFileEnv.js → fileEnv.js} +4 -4
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -9
- package/dist/cjs/node/prerender/index.js +1 -1
- package/dist/cjs/node/prerender/runPrerender.js +21 -13
- package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +5 -3
- package/dist/cjs/node/runtime/renderPage/{loadPageFilesServerSide.js → loadUserFilesServerSide.js} +5 -5
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -4
- package/dist/cjs/node/runtime/renderPage.js +2 -2
- package/dist/cjs/shared/hooks/getHook.js +14 -8
- package/dist/cjs/shared/misc/isRenderFailure.js +4 -0
- package/dist/cjs/shared/misc/pageContextInitIsPassedToClient.js +4 -0
- package/dist/cjs/shared/route/abort.js +15 -4
- package/dist/cjs/shared/route/loadPageRoutes.js +1 -9
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +27 -32
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +39 -55
- package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +1 -1
- package/dist/esm/client/client-routing-runtime/installClientRouter.js +8 -2
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +2 -2
- package/dist/esm/client/client-routing-runtime/onLinkClick.js +2 -2
- package/dist/esm/client/client-routing-runtime/prefetch.js +2 -2
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +209 -141
- package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +2 -2
- package/dist/esm/client/server-routing-runtime/getPageContext.js +5 -4
- package/dist/esm/client/shared/getPageContextSerializedInHtml.d.ts +0 -1
- package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -4
- package/dist/esm/client/shared/{loadPageFilesClientSide.d.ts → loadUserFilesClientSide.d.ts} +7 -6
- package/dist/esm/client/shared/{loadPageFilesClientSide.js → loadUserFilesClientSide.js} +4 -4
- package/dist/esm/node/cli/bin.js +3 -3
- package/dist/esm/node/plugin/index.js +2 -2
- package/dist/esm/node/plugin/plugins/autoFullBuild.js +3 -3
- package/dist/esm/node/plugin/plugins/envVars.js +1 -1
- package/dist/esm/node/plugin/plugins/fileEnv.d.ts +3 -0
- package/dist/esm/node/plugin/plugins/{assertFileEnv.js → fileEnv.js} +3 -3
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -9
- package/dist/esm/node/prerender/index.d.ts +1 -1
- package/dist/esm/node/prerender/index.js +1 -1
- package/dist/esm/node/prerender/runPrerender.d.ts +8 -8
- package/dist/esm/node/prerender/runPrerender.js +22 -14
- package/dist/esm/node/runtime/html/serializePageContextClientSide.d.ts +0 -1
- package/dist/esm/node/runtime/html/serializePageContextClientSide.js +5 -3
- package/dist/esm/node/runtime/renderPage/{loadPageFilesServerSide.d.ts → loadUserFilesServerSide.d.ts} +6 -6
- package/dist/esm/node/runtime/renderPage/{loadPageFilesServerSide.js → loadUserFilesServerSide.js} +4 -4
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -4
- package/dist/esm/node/runtime/renderPage.js +2 -2
- package/dist/esm/shared/hooks/getHook.d.ts +2 -0
- package/dist/esm/shared/hooks/getHook.js +13 -7
- package/dist/esm/shared/misc/isRenderFailure.d.ts +1 -0
- package/dist/esm/shared/misc/isRenderFailure.js +1 -0
- package/dist/esm/shared/misc/pageContextInitIsPassedToClient.d.ts +1 -0
- package/dist/esm/shared/misc/pageContextInitIsPassedToClient.js +1 -0
- package/dist/esm/shared/route/abort.d.ts +1 -1
- package/dist/esm/shared/route/abort.js +16 -5
- package/dist/esm/shared/route/loadPageRoutes.js +1 -9
- package/dist/esm/utils/projectInfo.d.ts +2 -2
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +1 -1
- 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 {
|
|
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/
|
|
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
|
-
|
|
23
|
-
const
|
|
24
|
-
assert(isClientSideNavigation === !
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
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 (
|
|
104
|
+
if (!isHydrationRender) {
|
|
105
|
+
assertHook(pageContext, 'onPageTransitionStart');
|
|
77
106
|
if (!globalObject.isTransitioning) {
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
globalObject.isTransitioning = true;
|
|
108
|
+
const onPageTransitionStartHook = getHook(pageContext, 'onPageTransitionStart');
|
|
109
|
+
if (onPageTransitionStartHook) {
|
|
110
|
+
const hook = onPageTransitionStartHook;
|
|
80
111
|
const { hookFn } = hook;
|
|
81
|
-
|
|
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
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
176
|
+
async function renderErrorPage(args) {
|
|
137
177
|
const pageContext = await getPageContextBegin();
|
|
138
178
|
if (isRenderOutdated())
|
|
139
179
|
return;
|
|
140
|
-
|
|
141
|
-
|
|
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 (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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
|
-
|
|
189
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
279
|
+
console.error(errErrorPage);
|
|
215
280
|
}
|
|
216
|
-
|
|
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
|
-
|
|
271
|
-
|
|
320
|
+
if (isRenderOutdated(true)) return
|
|
321
|
+
*/
|
|
272
322
|
// onHydrationEnd()
|
|
273
|
-
if (
|
|
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
|
-
|
|
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
|
|
343
|
+
// We abort *after* onHydrationEnd() is called
|
|
284
344
|
if (isRenderOutdated(true))
|
|
285
345
|
return;
|
|
286
346
|
// onPageTransitionEnd()
|
|
287
|
-
if (
|
|
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
|
-
|
|
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
|
|
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,
|
|
386
|
+
function handleErrorFetchingStaticAssets(err, pageContext, isHydrationRender) {
|
|
319
387
|
if (!isErrorFetchingStaticAssets(err)) {
|
|
320
388
|
return false;
|
|
321
389
|
}
|
|
322
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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,5 @@
|
|
|
1
1
|
import { parse } from '@brillout/json-serializer/parse';
|
|
2
|
-
import { hasProp, assert, assertUsage
|
|
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
|
}
|
package/dist/esm/client/shared/{loadPageFilesClientSide.d.ts → loadUserFilesClientSide.d.ts}
RENAMED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { loadUserFilesClientSide };
|
|
2
2
|
export { isErrorFetchingStaticAssets };
|
|
3
|
-
export type {
|
|
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
|
|
6
|
+
type PageContextUserFilesLoaded = PageContextExports & {
|
|
7
|
+
_pageFilesLoaded: PageFile[];
|
|
8
|
+
};
|
|
9
|
+
type PageContextUserFiles = {
|
|
7
10
|
_pageFilesAll: PageFile[];
|
|
8
11
|
_pageConfigs: PageConfigRuntime[];
|
|
9
12
|
};
|
|
10
|
-
declare function
|
|
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 {
|
|
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
|
|
8
|
-
const pageFilesClientSide = getPageFilesClientSide(
|
|
9
|
-
const pageConfig = findPageConfig(
|
|
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;
|
package/dist/esm/node/cli/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cac } from 'cac';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import {
|
|
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
|
|
14
|
-
|
|
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
|