vike 0.4.197 → 0.4.198
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/client/client-routing-runtime/prefetch/PrefetchSetting.js +2 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +14 -1
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +2 -2
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +26 -23
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.js → transformPointerImports.js} +3 -4
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +44 -47
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +16 -7
- package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
- package/dist/cjs/shared/page-configs/serialize/serializeConfigValues.js +2 -2
- package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
- package/dist/cjs/utils/isNpmPackage.js +4 -0
- package/dist/cjs/utils/isScriptFile.js +3 -3
- package/dist/cjs/utils/parseUrl.js +2 -10
- package/dist/esm/client/client-routing-runtime/entry.js +2 -2
- package/dist/esm/client/client-routing-runtime/getPageContextCurrent.d.ts +8 -0
- package/dist/esm/client/client-routing-runtime/getPageContextCurrent.js +13 -0
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +26 -16
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +34 -30
- package/dist/esm/client/client-routing-runtime/history.js +1 -1
- package/dist/esm/client/client-routing-runtime/initClientRouter.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/{installClientRouter.js → initClientRouter.js} +11 -8
- package/dist/esm/client/client-routing-runtime/initOnLinkClick.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/{onLinkClick.js → initOnLinkClick.js} +2 -2
- package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +1 -0
- package/dist/esm/client/client-routing-runtime/navigate.js +3 -2
- package/dist/esm/client/client-routing-runtime/normalizeUrlArgument.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/normalizeUrlArgument.js +14 -0
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +1 -1
- package/dist/esm/client/client-routing-runtime/prefetch/PrefetchSetting.d.ts +7 -0
- package/dist/esm/client/client-routing-runtime/prefetch/PrefetchSetting.js +1 -0
- package/dist/esm/client/client-routing-runtime/prefetch/getPrefetchSettings.d.ts +8 -7
- package/dist/esm/client/client-routing-runtime/prefetch/getPrefetchSettings.js +75 -67
- package/dist/esm/client/client-routing-runtime/prefetch.d.ts +29 -5
- package/dist/esm/client/client-routing-runtime/prefetch.js +196 -68
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +71 -24
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +14 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.d.ts +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +25 -22
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.d.ts → transformPointerImports.d.ts} +2 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.js → transformPointerImports.js} +3 -4
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +45 -48
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +16 -7
- package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
- package/dist/esm/shared/page-configs/Config.d.ts +10 -1
- package/dist/esm/shared/page-configs/serialize/serializeConfigValues.js +1 -1
- package/dist/esm/shared/types.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/utils/isNpmPackage.d.ts +2 -0
- package/dist/esm/utils/isNpmPackage.js +4 -0
- package/dist/esm/utils/isScriptFile.d.ts +2 -2
- package/dist/esm/utils/isScriptFile.js +3 -3
- package/dist/esm/utils/parseUrl.d.ts +2 -2
- package/dist/esm/utils/parseUrl.js +2 -10
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/package.json +1 -1
- package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/onLinkClick.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/prefetch/alreadyPrefetched.d.ts +0 -4
- package/dist/esm/client/client-routing-runtime/prefetch/alreadyPrefetched.js +0 -16
|
@@ -1,21 +1,51 @@
|
|
|
1
1
|
export { prefetch };
|
|
2
|
+
export { getPageContextPrefetched };
|
|
3
|
+
export { initLinkPrefetchHandlers };
|
|
4
|
+
export { populatePageContextPrefetchCache };
|
|
2
5
|
export { addLinkPrefetchHandlers };
|
|
3
|
-
|
|
6
|
+
export { addLinkPrefetchHandlers_watch };
|
|
7
|
+
export { addLinkPrefetchHandlers_unwatch };
|
|
8
|
+
import { assert, assertClientRouting, assertUsage, assertWarning, checkIfClientRouting, getGlobalObject, hasProp, objectAssign } from './utils.js';
|
|
4
9
|
import { isErrorFetchingStaticAssets, loadUserFilesClientSide } from '../shared/loadUserFilesClientSide.js';
|
|
5
10
|
import { skipLink } from './skipLink.js';
|
|
6
|
-
import { getPrefetchSettings } from './prefetch/getPrefetchSettings.js';
|
|
7
|
-
import { isAlreadyPrefetched, markAsAlreadyPrefetched } from './prefetch/alreadyPrefetched.js';
|
|
8
11
|
import { disableClientRouting } from './renderPageClientSide.js';
|
|
9
12
|
import { isClientSideRoutable } from './isClientSideRoutable.js';
|
|
10
13
|
import { createPageContext } from './createPageContext.js';
|
|
11
14
|
import { route } from '../../shared/route/index.js';
|
|
12
15
|
import { noRouteMatch } from '../../shared/route/noRouteMatch.js';
|
|
16
|
+
import { getPageContextFromServerHooks } from './getPageContextFromHooks.js';
|
|
17
|
+
import { getPageContextCurrent } from './getPageContextCurrent.js';
|
|
18
|
+
import { PAGE_CONTEXT_MAX_AGE_DEFAULT, getPrefetchSettings } from './prefetch/getPrefetchSettings.js';
|
|
13
19
|
import pc from '@brillout/picocolors';
|
|
20
|
+
import { normalizeUrlArgument } from './normalizeUrlArgument.js';
|
|
14
21
|
assertClientRouting();
|
|
15
|
-
const globalObject = getGlobalObject('prefetch.ts', {
|
|
16
|
-
|
|
22
|
+
const globalObject = getGlobalObject('prefetch.ts', {
|
|
23
|
+
linkPrefetchHandlerAdded: new WeakSet(),
|
|
24
|
+
addLinkPrefetchHandlers_debounce: null,
|
|
25
|
+
mutationObserver: new MutationObserver(addLinkPrefetchHandlers),
|
|
26
|
+
// `linkTags` [is automatically updated](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection#:~:text=An%20HTMLCollection%20in%20the%20HTML%20DOM%20is%20live%3B%20it%20is%20automatically%20updated%20when%20the%20underlying%20document%20is%20changed.)
|
|
27
|
+
linkTags: document.getElementsByTagName('A'),
|
|
28
|
+
prefetchedPageContexts: {}
|
|
29
|
+
});
|
|
30
|
+
function getPageContextPrefetched(pageContext) {
|
|
31
|
+
const prefetchSettings = getPrefetchSettings(pageContext, null);
|
|
32
|
+
// TODO/pageContext-prefetch: I guess we need linkTag to make this condition work
|
|
33
|
+
if (!prefetchSettings.pageContext)
|
|
34
|
+
return null;
|
|
35
|
+
const key = getCacheKey(pageContext.urlPathname);
|
|
36
|
+
const found = globalObject.prefetchedPageContexts[key];
|
|
37
|
+
if (!found || found.result.is404ServerSideRouted || isExpired(found))
|
|
38
|
+
return null;
|
|
39
|
+
const pageContextPrefetched = found.result.pageContextFromServerHooks;
|
|
40
|
+
/* TODO/pageContext-prefetch: make it work for when resultMaxAge is Infinity.
|
|
41
|
+
// We discard the prefetched pageContext whenever we use it, so that the user always sees fresh data upon naivgating.
|
|
42
|
+
delete globalObject.prefetchedPageContexts[key]
|
|
43
|
+
*/
|
|
44
|
+
return pageContextPrefetched;
|
|
45
|
+
}
|
|
46
|
+
async function prefetchAssets(pageContextLink) {
|
|
17
47
|
try {
|
|
18
|
-
await loadUserFilesClientSide(pageId,
|
|
48
|
+
await loadUserFilesClientSide(pageContextLink.pageId, pageContextLink._pageFilesAll, pageContextLink._pageConfigs);
|
|
19
49
|
}
|
|
20
50
|
catch (err) {
|
|
21
51
|
if (isErrorFetchingStaticAssets(err)) {
|
|
@@ -26,6 +56,36 @@ async function prefetchAssets(pageId, pageContext) {
|
|
|
26
56
|
}
|
|
27
57
|
}
|
|
28
58
|
}
|
|
59
|
+
async function prefetchPageContextFromServerHooks(pageContextLink, resultMaxAge) {
|
|
60
|
+
const result = await getPageContextFromServerHooks(pageContextLink, false);
|
|
61
|
+
setPageContextPrefetchCache(pageContextLink, result, resultMaxAge);
|
|
62
|
+
}
|
|
63
|
+
function populatePageContextPrefetchCache(pageContext /*& PageContextExports*/, result) {
|
|
64
|
+
// TODO/pageContext-prefetch: replace with using pageContext.config.prerender instead. (For being able to do that: eager configs need to be accessible without have to use PageContextExports as it isn't available here.)
|
|
65
|
+
if (!isBrilloutDocpress())
|
|
66
|
+
return;
|
|
67
|
+
setPageContextPrefetchCache(pageContext, result, null);
|
|
68
|
+
}
|
|
69
|
+
function setPageContextPrefetchCache(pageContext, result, resultMaxAge) {
|
|
70
|
+
if (resultMaxAge === null)
|
|
71
|
+
resultMaxAge = getResultMaxAge();
|
|
72
|
+
const key = getCacheKey(pageContext.urlPathname);
|
|
73
|
+
assert(isBrilloutDocpress()); // Ensure this API isn't used by anyone else
|
|
74
|
+
globalObject.prefetchedPageContexts[key] = {
|
|
75
|
+
resultFetchedAt: Date.now(),
|
|
76
|
+
resultMaxAge,
|
|
77
|
+
result
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function getResultMaxAge() {
|
|
81
|
+
const pageContextCurrent = getPageContextCurrent();
|
|
82
|
+
// TODO/pageContext-prefetch: remove this dirty hack used by @brillout/docpress and, instead, use Vike's default if pageContextCurrent isn't defined yet.
|
|
83
|
+
if (!pageContextCurrent)
|
|
84
|
+
return Infinity;
|
|
85
|
+
const prefetchSettings = getPrefetchSettings(pageContextCurrent, null);
|
|
86
|
+
const resultMaxAge = typeof prefetchSettings.pageContext === 'number' ? prefetchSettings.pageContext : PAGE_CONTEXT_MAX_AGE_DEFAULT;
|
|
87
|
+
return resultMaxAge;
|
|
88
|
+
}
|
|
29
89
|
/**
|
|
30
90
|
* Programmatically prefetch client assets.
|
|
31
91
|
*
|
|
@@ -33,85 +93,153 @@ async function prefetchAssets(pageId, pageContext) {
|
|
|
33
93
|
*
|
|
34
94
|
* @param url - The URL of the page you want to prefetch.
|
|
35
95
|
*/
|
|
36
|
-
async function prefetch(url) {
|
|
96
|
+
async function prefetch(url, options) {
|
|
37
97
|
assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
|
|
38
98
|
showStackTrace: true
|
|
39
99
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
markAsAlreadyPrefetched(url);
|
|
45
|
-
const pageContext = await createPageContext(url);
|
|
46
|
-
let pageContextFromRoute;
|
|
47
|
-
try {
|
|
48
|
-
pageContextFromRoute = await route(pageContext);
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// If a route() hook has a bug or `throw render()` / `throw redirect()`
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const pageId = pageContextFromRoute.pageId;
|
|
55
|
-
if (!pageId) {
|
|
56
|
-
assertWarning(false, `${errPrefix} ${pc.string(url)} ${noRouteMatch}`, {
|
|
100
|
+
url = normalizeUrlArgument(url, 'prefetch');
|
|
101
|
+
const pageContextLink = await getPageContextLink(url);
|
|
102
|
+
if (!pageContextLink?.pageId) {
|
|
103
|
+
assertWarning(false, `[prefetch(url)] ${pc.string(url)} ${noRouteMatch}`, {
|
|
57
104
|
showStackTrace: true,
|
|
58
105
|
onlyOnce: false
|
|
59
106
|
});
|
|
60
107
|
return;
|
|
61
108
|
}
|
|
62
|
-
|
|
109
|
+
assert(hasProp(pageContextLink, 'pageId', 'string')); // help TypeScript
|
|
110
|
+
await Promise.all([
|
|
111
|
+
(async () => {
|
|
112
|
+
if (options?.staticAssets !== false) {
|
|
113
|
+
await prefetchAssets(pageContextLink);
|
|
114
|
+
}
|
|
115
|
+
})(),
|
|
116
|
+
(async () => {
|
|
117
|
+
if (options?.pageContext !== false) {
|
|
118
|
+
const resultMaxAge = typeof options?.pageContext === 'number' ? options.pageContext : null;
|
|
119
|
+
await prefetchPageContextFromServerHooks(pageContextLink, resultMaxAge);
|
|
120
|
+
}
|
|
121
|
+
})()
|
|
122
|
+
]);
|
|
63
123
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const url = linkTag.getAttribute('href');
|
|
73
|
-
if (skipLink(linkTag))
|
|
74
|
-
return;
|
|
75
|
-
assert(url);
|
|
76
|
-
if (isAlreadyPrefetched(url))
|
|
77
|
-
return;
|
|
78
|
-
const { prefetchStaticAssets } = getPrefetchSettings(pageContext, linkTag);
|
|
79
|
-
if (!prefetchStaticAssets)
|
|
80
|
-
return;
|
|
81
|
-
if (prefetchStaticAssets === 'hover') {
|
|
82
|
-
linkTag.addEventListener('mouseover', () => {
|
|
83
|
-
prefetchIfPossible(url);
|
|
84
|
-
});
|
|
85
|
-
linkTag.addEventListener('touchstart', () => {
|
|
86
|
-
prefetchIfPossible(url);
|
|
87
|
-
}, { passive: true });
|
|
124
|
+
// Lazy execution logic copied from: https://github.com/withastro/astro/blob/2594eb088d53a98181ac820243bcb1a765856ecf/packages/astro/src/runtime/client/dev-toolbar/apps/audit/index.ts#L53-L72
|
|
125
|
+
function addLinkPrefetchHandlers() {
|
|
126
|
+
if (globalObject.addLinkPrefetchHandlers_debounce)
|
|
127
|
+
clearTimeout(globalObject.addLinkPrefetchHandlers_debounce);
|
|
128
|
+
globalObject.addLinkPrefetchHandlers_debounce = setTimeout(() => {
|
|
129
|
+
// Wait for the next idle period, as it is less likely to interfere with any other work the browser is doing post-mutation.
|
|
130
|
+
if ('requestIdleCallback' in window) {
|
|
131
|
+
requestIdleCallback(addLinkPrefetchHandlers_apply, { timeout: 300 });
|
|
88
132
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (entry.isIntersecting) {
|
|
93
|
-
prefetchIfPossible(url);
|
|
94
|
-
observer.disconnect();
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
observer.observe(linkTag);
|
|
133
|
+
else {
|
|
134
|
+
// Fallback for old versions of Safari, we'll assume that things are less likely to be busy after 150ms.
|
|
135
|
+
setTimeout(addLinkPrefetchHandlers_apply, 150);
|
|
99
136
|
}
|
|
137
|
+
}, 250);
|
|
138
|
+
}
|
|
139
|
+
function initLinkPrefetchHandlers() {
|
|
140
|
+
addLinkPrefetchHandlers();
|
|
141
|
+
}
|
|
142
|
+
function addLinkPrefetchHandlers_watch() {
|
|
143
|
+
// Notes about performance:
|
|
144
|
+
// - https://stackoverflow.com/questions/31659567/performance-of-mutationobserver-to-detect-nodes-in-entire-dom/39332340#39332340
|
|
145
|
+
// - https://news.ycombinator.com/item?id=15274211
|
|
146
|
+
// - https://github.com/kubetail-org/sentineljs
|
|
147
|
+
// - https://stackoverflow.com/questions/55046093/listening-for-changes-in-htmlcollection-or-achieving-a-similar-effect
|
|
148
|
+
globalObject.mutationObserver.observe(document.body, {
|
|
149
|
+
childList: true,
|
|
150
|
+
subtree: true
|
|
100
151
|
});
|
|
101
152
|
}
|
|
102
|
-
|
|
103
|
-
|
|
153
|
+
function addLinkPrefetchHandlers_unwatch() {
|
|
154
|
+
globalObject.mutationObserver.disconnect();
|
|
155
|
+
}
|
|
156
|
+
function addLinkPrefetchHandlers_apply() {
|
|
157
|
+
for (let linkTag of globalObject.linkTags) {
|
|
158
|
+
if (globalObject.linkPrefetchHandlerAdded.has(linkTag))
|
|
159
|
+
continue;
|
|
160
|
+
globalObject.linkPrefetchHandlerAdded.add(linkTag);
|
|
161
|
+
if (skipLink(linkTag))
|
|
162
|
+
continue;
|
|
163
|
+
linkTag.addEventListener('mouseover', () => {
|
|
164
|
+
prefetchOnEvent(linkTag, 'hover');
|
|
165
|
+
}, { passive: true });
|
|
166
|
+
linkTag.addEventListener('touchstart', () => {
|
|
167
|
+
prefetchOnEvent(linkTag, 'hover');
|
|
168
|
+
}, { passive: true });
|
|
169
|
+
const observer = new IntersectionObserver((entries) => {
|
|
170
|
+
entries.forEach((entry) => {
|
|
171
|
+
if (entry.isIntersecting) {
|
|
172
|
+
prefetchOnEvent(linkTag, 'viewport');
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
observer.observe(linkTag);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function prefetchOnEvent(linkTag, event) {
|
|
180
|
+
let prefetchSettings;
|
|
181
|
+
const pageContextCurrent = getPageContextCurrent();
|
|
182
|
+
if (pageContextCurrent) {
|
|
183
|
+
prefetchSettings = getPrefetchSettings(pageContextCurrent, linkTag);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// TODO/pageContext-prefetch: remove this dirty hack used by @brillout/docpress and, instead, use Vike's default if pageContextCurrent isn't defined yet.
|
|
187
|
+
prefetchSettings = { staticAssets: 'hover', pageContext: Infinity };
|
|
188
|
+
}
|
|
189
|
+
// Check again in case DOM was manipulated since last check
|
|
190
|
+
if (skipLink(linkTag))
|
|
191
|
+
return;
|
|
192
|
+
const urlOfLink = linkTag.getAttribute('href');
|
|
193
|
+
const pageContextLink = await getPageContextLink(urlOfLink);
|
|
194
|
+
if (!pageContextLink?.pageId)
|
|
195
|
+
return;
|
|
196
|
+
assert(hasProp(pageContextLink, 'pageId', 'string')); // help TypeScript
|
|
197
|
+
if (!(await isClientSideRoutable(pageContextLink.pageId, pageContextLink)))
|
|
198
|
+
return;
|
|
199
|
+
await Promise.all([
|
|
200
|
+
(async () => {
|
|
201
|
+
if (prefetchSettings.staticAssets === event) {
|
|
202
|
+
await prefetchAssets(pageContextLink);
|
|
203
|
+
}
|
|
204
|
+
})(),
|
|
205
|
+
(async () => {
|
|
206
|
+
if (event !== 'viewport' && prefetchSettings.pageContext) {
|
|
207
|
+
const key = getCacheKey(urlOfLink);
|
|
208
|
+
const found = globalObject.prefetchedPageContexts[key];
|
|
209
|
+
if (!found || isExpired(found)) {
|
|
210
|
+
// TODO/pageContext-prefetch: move this logic in getPrefetchSettings()
|
|
211
|
+
const resultMaxAge = prefetchSettings.pageContext;
|
|
212
|
+
await prefetchPageContextFromServerHooks(pageContextLink, resultMaxAge);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
})()
|
|
216
|
+
]);
|
|
217
|
+
}
|
|
218
|
+
function isExpired(found) {
|
|
219
|
+
return Date.now() - found.resultFetchedAt > found.resultMaxAge;
|
|
220
|
+
}
|
|
221
|
+
// TODO/next-major-release: make it sync
|
|
222
|
+
async function getPageContextLink(urlOfLink) {
|
|
223
|
+
const pageContextLink = await createPageContext(urlOfLink);
|
|
104
224
|
let pageContextFromRoute;
|
|
105
225
|
try {
|
|
106
|
-
pageContextFromRoute = await route(
|
|
226
|
+
pageContextFromRoute = await route(pageContextLink);
|
|
107
227
|
}
|
|
108
228
|
catch {
|
|
109
229
|
// If a route() hook has a bug or `throw render()` / `throw redirect()`
|
|
110
|
-
return;
|
|
230
|
+
return null;
|
|
111
231
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
232
|
+
objectAssign(pageContextLink, pageContextFromRoute);
|
|
233
|
+
return pageContextLink;
|
|
234
|
+
}
|
|
235
|
+
function getCacheKey(url) {
|
|
236
|
+
if (url.startsWith('#'))
|
|
237
|
+
url = '/';
|
|
238
|
+
assert(url.startsWith('/'), { urlPathname: url });
|
|
239
|
+
const key = url.split('#')[0];
|
|
240
|
+
return key;
|
|
241
|
+
}
|
|
242
|
+
// TODO/pageContext-prefetch: remove
|
|
243
|
+
function isBrilloutDocpress() {
|
|
244
|
+
return '_isBrilloutDocpress' in window;
|
|
117
245
|
}
|
|
@@ -3,9 +3,9 @@ export { getRenderCount };
|
|
|
3
3
|
export { disableClientRouting };
|
|
4
4
|
export { firstRenderStartPromise };
|
|
5
5
|
import { assert, getCurrentUrl, isSameErrorMessage, objectAssign, redirectHard, getGlobalObject, executeHook, hasProp, augmentType, genPromise, isCallable } from './utils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getPageContextFromClientHooks, getPageContextFromServerHooks, getPageContextFromHooks_isHydration, getPageContextFromHooks_serialized, setPageContextInitIsPassedToClient } from './getPageContextFromHooks.js';
|
|
7
7
|
import { createPageContext } from './createPageContext.js';
|
|
8
|
-
import { addLinkPrefetchHandlers } from './prefetch.js';
|
|
8
|
+
import { addLinkPrefetchHandlers, addLinkPrefetchHandlers_unwatch, addLinkPrefetchHandlers_watch, getPageContextPrefetched, populatePageContextPrefetchCache } from './prefetch.js';
|
|
9
9
|
import { assertInfo, assertWarning, isReact } from './utils.js';
|
|
10
10
|
import { executeOnRenderClientHook } from '../shared/executeOnRenderClientHook.js';
|
|
11
11
|
import { assertHook, getHook } from '../../shared/hooks/getHook.js';
|
|
@@ -18,6 +18,7 @@ import { setScrollPosition } from './setScrollPosition.js';
|
|
|
18
18
|
import { updateState } from './onBrowserHistoryNavigation.js';
|
|
19
19
|
import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
|
|
20
20
|
import { getErrorPageId } from '../../shared/error-page.js';
|
|
21
|
+
import { setPageContextCurrent } from './getPageContextCurrent.js';
|
|
21
22
|
import { getRouteStringParameterList } from '../../shared/route/resolveRouteString.js';
|
|
22
23
|
const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
|
|
23
24
|
const { promise: firstRenderStartPromise, resolve: firstRenderStartPromiseResolve } = genPromise();
|
|
@@ -32,6 +33,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
32
33
|
const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
|
|
33
34
|
let { scrollTarget } = renderArgs;
|
|
34
35
|
const { previousPageContext } = globalObject;
|
|
36
|
+
addLinkPrefetchHandlers_unwatch();
|
|
35
37
|
const { isRenderOutdated, setHydrationCanBeAborted, isFirstRender } = getIsRenderOutdated();
|
|
36
38
|
// Note that pageContext.isHydration isn't equivalent to isFirstRender
|
|
37
39
|
// - Thus pageContext.isHydration isn't equivalent to !pageContext.isClientSideNavigation
|
|
@@ -51,7 +53,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
51
53
|
const onError = async (err) => {
|
|
52
54
|
await renderErrorPage({ err });
|
|
53
55
|
};
|
|
54
|
-
const pageContext = await getPageContextBegin();
|
|
56
|
+
const pageContext = await getPageContextBegin(false);
|
|
55
57
|
if (isRenderOutdated())
|
|
56
58
|
return;
|
|
57
59
|
// onPageTransitionStart()
|
|
@@ -79,10 +81,13 @@ async function renderPageClientSide(renderArgs) {
|
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
// Route
|
|
82
|
-
let pageContextRouted;
|
|
83
84
|
if (isFirstRender) {
|
|
84
85
|
const pageContextSerialized = getPageContextFromHooks_serialized();
|
|
85
|
-
|
|
86
|
+
// TODO/eventually: create helper assertPageContextFromHook()
|
|
87
|
+
assert(!('urlOriginal' in pageContextSerialized));
|
|
88
|
+
objectAssign(pageContext, pageContextSerialized);
|
|
89
|
+
// TODO/pageContext-prefetch: remove or change, because this only makes sense for a pre-rendered page
|
|
90
|
+
populatePageContextPrefetchCache(pageContext, { pageContextFromServerHooks: pageContextSerialized });
|
|
86
91
|
}
|
|
87
92
|
else {
|
|
88
93
|
let pageContextFromRoute;
|
|
@@ -123,10 +128,10 @@ async function renderPageClientSide(renderArgs) {
|
|
|
123
128
|
// Skip's Vike's rendering; let the user handle the navigation
|
|
124
129
|
return;
|
|
125
130
|
}
|
|
126
|
-
|
|
131
|
+
// TODO/eventually: create helper assertPageContextFromHook()
|
|
132
|
+
assert(!('urlOriginal' in pageContextFromRoute));
|
|
133
|
+
objectAssign(pageContext, pageContextFromRoute);
|
|
127
134
|
}
|
|
128
|
-
assert(!('urlOriginal' in pageContextRouted));
|
|
129
|
-
objectAssign(pageContext, pageContextRouted);
|
|
130
135
|
try {
|
|
131
136
|
objectAssign(pageContext, await loadUserFilesClientSide(pageContext.pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
|
|
132
137
|
}
|
|
@@ -142,6 +147,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
142
147
|
}
|
|
143
148
|
if (isRenderOutdated())
|
|
144
149
|
return;
|
|
150
|
+
setPageContextCurrent(pageContext);
|
|
145
151
|
// Set global hydrationCanBeAborted
|
|
146
152
|
if (pageContext.exports.hydrationCanBeAborted) {
|
|
147
153
|
setHydrationCanBeAborted();
|
|
@@ -149,7 +155,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
149
155
|
else {
|
|
150
156
|
assertWarning(!isReact(), 'You seem to be using React; we recommend setting hydrationCanBeAborted to true, see https://vike.dev/hydrationCanBeAborted', { onlyOnce: true });
|
|
151
157
|
}
|
|
152
|
-
// There wasn't any `await` but
|
|
158
|
+
// There wasn't any `await` but the isRenderOutdated() return value may have changed because we called setHydrationCanBeAborted()
|
|
153
159
|
if (isRenderOutdated())
|
|
154
160
|
return;
|
|
155
161
|
// Get pageContext from hooks (fetched from server, and/or directly called on the client-side)
|
|
@@ -170,9 +176,35 @@ async function renderPageClientSide(renderArgs) {
|
|
|
170
176
|
await renderPageView(pageContext);
|
|
171
177
|
}
|
|
172
178
|
else {
|
|
173
|
-
|
|
179
|
+
// Fetch pageContext from server-side hooks
|
|
180
|
+
let pageContextFromServerHooks;
|
|
181
|
+
const pageContextPrefetched = getPageContextPrefetched(pageContext);
|
|
182
|
+
if (pageContextPrefetched) {
|
|
183
|
+
pageContextFromServerHooks = pageContextPrefetched;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
try {
|
|
187
|
+
const result = await getPageContextFromServerHooks(pageContext, false);
|
|
188
|
+
if (result.is404ServerSideRouted)
|
|
189
|
+
return;
|
|
190
|
+
pageContextFromServerHooks = result.pageContextFromServerHooks;
|
|
191
|
+
// TODO/pageContext-prefetch: remove or change, because this only makes sense for a pre-rendered page
|
|
192
|
+
populatePageContextPrefetchCache(pageContext, result);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
await onError(err);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (isRenderOutdated())
|
|
200
|
+
return;
|
|
201
|
+
// TODO/eventually: create helper assertPageContextFromHook()
|
|
202
|
+
assert(!('urlOriginal' in pageContextFromServerHooks));
|
|
203
|
+
objectAssign(pageContext, pageContextFromServerHooks);
|
|
204
|
+
// Get pageContext from client-side hooks
|
|
205
|
+
let pageContextFromClientHooks;
|
|
174
206
|
try {
|
|
175
|
-
|
|
207
|
+
pageContextFromClientHooks = await getPageContextFromClientHooks(pageContext, false);
|
|
176
208
|
}
|
|
177
209
|
catch (err) {
|
|
178
210
|
await onError(err);
|
|
@@ -180,18 +212,16 @@ async function renderPageClientSide(renderArgs) {
|
|
|
180
212
|
}
|
|
181
213
|
if (isRenderOutdated())
|
|
182
214
|
return;
|
|
183
|
-
|
|
184
|
-
return;
|
|
185
|
-
augmentType(pageContext, res.pageContextAugmented);
|
|
186
|
-
// Render page view
|
|
215
|
+
augmentType(pageContext, pageContextFromClientHooks);
|
|
187
216
|
await renderPageView(pageContext);
|
|
188
217
|
}
|
|
189
218
|
}
|
|
190
|
-
async function getPageContextBegin() {
|
|
219
|
+
async function getPageContextBegin(isForErrorPage) {
|
|
191
220
|
const pageContext = await createPageContext(urlOriginal);
|
|
192
221
|
objectAssign(pageContext, {
|
|
193
222
|
isBackwardNavigation,
|
|
194
223
|
isClientSideNavigation,
|
|
224
|
+
isHydration: isFirstRender && !isForErrorPage,
|
|
195
225
|
_previousPageContext: previousPageContext
|
|
196
226
|
});
|
|
197
227
|
{
|
|
@@ -226,7 +256,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
226
256
|
// We handle the abort error down below.
|
|
227
257
|
}
|
|
228
258
|
}
|
|
229
|
-
const pageContext = await getPageContextBegin();
|
|
259
|
+
const pageContext = await getPageContextBegin(true);
|
|
230
260
|
if (isRenderOutdated())
|
|
231
261
|
return;
|
|
232
262
|
if (args.is404)
|
|
@@ -310,21 +340,34 @@ async function renderPageClientSide(renderArgs) {
|
|
|
310
340
|
}
|
|
311
341
|
if (isRenderOutdated())
|
|
312
342
|
return;
|
|
313
|
-
|
|
343
|
+
setPageContextCurrent(pageContext);
|
|
344
|
+
let pageContextFromServerHooks;
|
|
314
345
|
try {
|
|
315
|
-
|
|
346
|
+
const result = await getPageContextFromServerHooks(pageContext, true);
|
|
347
|
+
if (result.is404ServerSideRouted)
|
|
348
|
+
return;
|
|
349
|
+
pageContextFromServerHooks = result.pageContextFromServerHooks;
|
|
316
350
|
}
|
|
317
351
|
catch (err) {
|
|
318
|
-
// - When user hasn't defined a `_error.page.js` file
|
|
319
|
-
// - Some Vike unpexected internal error
|
|
320
352
|
onError(err);
|
|
321
353
|
return;
|
|
322
354
|
}
|
|
323
355
|
if (isRenderOutdated())
|
|
324
356
|
return;
|
|
325
|
-
|
|
357
|
+
// TODO/eventually: create helper assertPageContextFromHook()
|
|
358
|
+
assert(!('urlOriginal' in pageContextFromServerHooks));
|
|
359
|
+
objectAssign(pageContext, pageContextFromServerHooks);
|
|
360
|
+
let pageContextFromClientHooks;
|
|
361
|
+
try {
|
|
362
|
+
pageContextFromClientHooks = await getPageContextFromClientHooks(pageContext, true);
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
onError(err);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (isRenderOutdated())
|
|
326
369
|
return;
|
|
327
|
-
augmentType(pageContext,
|
|
370
|
+
augmentType(pageContext, pageContextFromClientHooks);
|
|
328
371
|
objectAssign(pageContext, { routeParams: {} });
|
|
329
372
|
await renderPageView(pageContext, args);
|
|
330
373
|
}
|
|
@@ -372,7 +415,6 @@ async function renderPageClientSide(renderArgs) {
|
|
|
372
415
|
/* We don't abort in order to ensure that onHydrationEnd() is called: we abort only after onHydrationEnd() is called.
|
|
373
416
|
if (isRenderOutdated(true)) return
|
|
374
417
|
*/
|
|
375
|
-
addLinkPrefetchHandlers(pageContext);
|
|
376
418
|
// onHydrationEnd()
|
|
377
419
|
if (isFirstRender && !onRenderClientError) {
|
|
378
420
|
assertHook(pageContext, 'onHydrationEnd');
|
|
@@ -427,6 +469,11 @@ async function renderPageClientSide(renderArgs) {
|
|
|
427
469
|
setScrollPosition(scrollTarget);
|
|
428
470
|
browserNativeScrollRestoration_disable();
|
|
429
471
|
setInitialRenderIsDone();
|
|
472
|
+
if (pageContext._hasPageContextFromServer)
|
|
473
|
+
setPageContextInitIsPassedToClient(pageContext);
|
|
474
|
+
// Add link prefetch handlers
|
|
475
|
+
addLinkPrefetchHandlers_watch();
|
|
476
|
+
addLinkPrefetchHandlers();
|
|
430
477
|
}
|
|
431
478
|
}
|
|
432
479
|
function changeUrl(url, overwriteLastHistoryEntry) {
|
|
@@ -67,6 +67,11 @@ const configDefinitionsBuiltIn = {
|
|
|
67
67
|
hydrationCanBeAborted: {
|
|
68
68
|
env: { client: true }
|
|
69
69
|
},
|
|
70
|
+
prefetch: {
|
|
71
|
+
env: { client: true },
|
|
72
|
+
eager: true
|
|
73
|
+
},
|
|
74
|
+
// TODO/v1-release: remove
|
|
70
75
|
prefetchStaticAssets: {
|
|
71
76
|
env: { client: true }
|
|
72
77
|
},
|
|
@@ -100,10 +105,12 @@ const configDefinitionsBuiltIn = {
|
|
|
100
105
|
},
|
|
101
106
|
onBeforeRenderEnv: {
|
|
102
107
|
env: { client: true },
|
|
108
|
+
eager: true,
|
|
103
109
|
_computed: (configValueSources) => !isConfigSet(configValueSources, 'onBeforeRender') ? null : getConfigEnv(configValueSources, 'onBeforeRender')
|
|
104
110
|
},
|
|
105
111
|
dataEnv: {
|
|
106
112
|
env: { client: true },
|
|
113
|
+
eager: true,
|
|
107
114
|
_computed: (configValueSources) => !isConfigSet(configValueSources, 'data') ? null : getConfigEnv(configValueSources, 'data')
|
|
108
115
|
},
|
|
109
116
|
hooksTimeout: {
|
|
@@ -149,7 +156,13 @@ function getConfigEnv(configValueSources, configName) {
|
|
|
149
156
|
const configValueSource = getConfigValueSource(configValueSources, configName);
|
|
150
157
|
if (!configValueSource)
|
|
151
158
|
return null;
|
|
152
|
-
|
|
159
|
+
const { configEnv } = configValueSource;
|
|
160
|
+
const env = {};
|
|
161
|
+
if (configEnv.client)
|
|
162
|
+
env.client = true;
|
|
163
|
+
if (configEnv.server)
|
|
164
|
+
env.server = true;
|
|
165
|
+
return env;
|
|
153
166
|
}
|
|
154
167
|
function isConfigSet(configValueSources, configName) {
|
|
155
168
|
const configValueSource = getConfigValueSource(configValueSources, configName);
|
package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js
CHANGED
|
@@ -6,7 +6,7 @@ import { assert, assertUsage, hasProp, assertIsNotProductionRuntime } from '../.
|
|
|
6
6
|
import { transpileAndExecuteFile } from './transpileAndExecuteFile.js';
|
|
7
7
|
import { assertPlusFileExport } from '../../../../../../shared/page-configs/assertPlusFileExport.js';
|
|
8
8
|
import pc from '@brillout/picocolors';
|
|
9
|
-
import { parsePointerImportData } from './
|
|
9
|
+
import { parsePointerImportData } from './transformPointerImports.js';
|
|
10
10
|
import { getConfigFileExport } from '../getConfigFileExport.js';
|
|
11
11
|
import { resolvePointerImport } from './resolvePointerImport.js';
|
|
12
12
|
assertIsNotProductionRuntime();
|
|
@@ -2,7 +2,7 @@ export { resolvePointerImportOfConfig };
|
|
|
2
2
|
export { resolvePointerImport };
|
|
3
3
|
export { clearFilesEnvMap };
|
|
4
4
|
import type { ConfigEnvInternal, DefinedAtFilePath } from '../../../../../../shared/page-configs/PageConfig.js';
|
|
5
|
-
import { type PointerImportData } from './
|
|
5
|
+
import { type PointerImportData } from './transformPointerImports.js';
|
|
6
6
|
import type { FilePath, FilePathResolved } from '../../../../../../shared/page-configs/FilePath.js';
|
|
7
7
|
type PointerImportResolved = DefinedAtFilePath & {
|
|
8
8
|
fileExportName: string;
|