vike 0.4.197 → 0.4.198-commit-081c85f

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/client/client-routing-runtime/prefetch/PrefetchSetting.js +2 -0
  2. package/dist/cjs/node/plugin/plugins/fileEnv.js +3 -0
  3. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +14 -1
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +2 -2
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +26 -23
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.js → transformPointerImports.js} +3 -4
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +44 -47
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +16 -7
  9. package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
  10. package/dist/cjs/shared/page-configs/serialize/serializeConfigValues.js +2 -2
  11. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  12. package/dist/cjs/utils/isNpmPackage.js +4 -0
  13. package/dist/cjs/utils/isScriptFile.js +3 -3
  14. package/dist/cjs/utils/parseUrl.js +2 -10
  15. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  16. package/dist/esm/client/client-routing-runtime/getPageContextCurrent.d.ts +8 -0
  17. package/dist/esm/client/client-routing-runtime/getPageContextCurrent.js +13 -0
  18. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +26 -16
  19. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +34 -30
  20. package/dist/esm/client/client-routing-runtime/history.js +1 -1
  21. package/dist/esm/client/client-routing-runtime/initClientRouter.d.ts +2 -0
  22. package/dist/esm/client/client-routing-runtime/{installClientRouter.js → initClientRouter.js} +11 -8
  23. package/dist/esm/client/client-routing-runtime/initOnLinkClick.d.ts +2 -0
  24. package/dist/esm/client/client-routing-runtime/{onLinkClick.js → initOnLinkClick.js} +2 -2
  25. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +1 -0
  26. package/dist/esm/client/client-routing-runtime/navigate.js +3 -2
  27. package/dist/esm/client/client-routing-runtime/normalizeUrlArgument.d.ts +2 -0
  28. package/dist/esm/client/client-routing-runtime/normalizeUrlArgument.js +14 -0
  29. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +1 -1
  30. package/dist/esm/client/client-routing-runtime/prefetch/PrefetchSetting.d.ts +7 -0
  31. package/dist/esm/client/client-routing-runtime/prefetch/PrefetchSetting.js +1 -0
  32. package/dist/esm/client/client-routing-runtime/prefetch/getPrefetchSettings.d.ts +8 -7
  33. package/dist/esm/client/client-routing-runtime/prefetch/getPrefetchSettings.js +75 -67
  34. package/dist/esm/client/client-routing-runtime/prefetch.d.ts +29 -5
  35. package/dist/esm/client/client-routing-runtime/prefetch.js +196 -68
  36. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +71 -24
  37. package/dist/esm/node/plugin/plugins/fileEnv.js +3 -0
  38. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +14 -1
  39. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +1 -1
  40. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.d.ts +1 -1
  41. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +25 -22
  42. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.d.ts → transformPointerImports.d.ts} +2 -2
  43. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformFileImports.js → transformPointerImports.js} +3 -4
  44. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +45 -48
  45. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +16 -7
  46. package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
  47. package/dist/esm/shared/page-configs/Config.d.ts +10 -1
  48. package/dist/esm/shared/page-configs/serialize/serializeConfigValues.js +1 -1
  49. package/dist/esm/shared/types.d.ts +1 -1
  50. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  51. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  52. package/dist/esm/utils/isNpmPackage.d.ts +2 -0
  53. package/dist/esm/utils/isNpmPackage.js +4 -0
  54. package/dist/esm/utils/isScriptFile.d.ts +2 -2
  55. package/dist/esm/utils/isScriptFile.js +3 -3
  56. package/dist/esm/utils/parseUrl.d.ts +2 -2
  57. package/dist/esm/utils/parseUrl.js +2 -10
  58. package/dist/esm/utils/projectInfo.d.ts +1 -1
  59. package/package.json +1 -1
  60. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +0 -2
  61. package/dist/esm/client/client-routing-runtime/onLinkClick.d.ts +0 -2
  62. package/dist/esm/client/client-routing-runtime/prefetch/alreadyPrefetched.d.ts +0 -4
  63. package/dist/esm/client/client-routing-runtime/prefetch/alreadyPrefetched.js +0 -16
@@ -1,6 +1,10 @@
1
1
  export { getPageContextFromHooks_isHydration };
2
- export { getPageContextFromHooks_isNotHydration };
3
2
  export { getPageContextFromHooks_serialized };
3
+ export { getPageContextFromServerHooks };
4
+ export { getPageContextFromClientHooks };
5
+ export { setPageContextInitIsPassedToClient };
6
+ export type { PageContextFromServerHooks };
7
+ export type { PageContextFromClientHooks };
4
8
  import type { PageContextExports, PageFile } from '../../shared/getPageFiles.js';
5
9
  import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
6
10
  type PageContext = {
@@ -15,25 +19,31 @@ type PageContextSerialized = {
15
19
  };
16
20
  declare function getPageContextFromHooks_serialized(): PageContextSerialized & {
17
21
  routeParams: Record<string, string>;
22
+ _hasPageContextFromServer: true;
18
23
  };
19
- declare function getPageContextFromHooks_isHydration(pageContext: PageContextSerialized & PageContext & PageContextExports): Promise<PageContextSerialized & PageContext & PageContextExports & {
20
- isHydration: true;
21
- _hasPageContextFromClient: false;
24
+ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSerialized & PageContext & PageContextExports & {
25
+ _hasPageContextFromServer: true;
26
+ }): Promise<PageContextSerialized & PageContext & PageContextExports & {
22
27
  _hasPageContextFromServer: true;
28
+ } & {
29
+ _hasPageContextFromClient: boolean;
23
30
  }>;
24
- declare function getPageContextFromHooks_isNotHydration(pageContext: {
31
+ type PageContextFromServerHooks = {
32
+ _hasPageContextFromServer: boolean;
33
+ };
34
+ declare function getPageContextFromServerHooks(pageContext: {
25
35
  pageId: string;
26
- } & PageContext & PageContextExports, isErrorPage: boolean): Promise<{
27
- is404ServerSideRouted: boolean;
28
- pageContextAugmented?: undefined;
36
+ } & PageContext, isErrorPage: boolean): Promise<{
37
+ is404ServerSideRouted: true;
29
38
  } | {
30
- pageContextAugmented: {
31
- pageId: string;
32
- } & PageContext & PageContextExports & {
33
- isHydration: false;
34
- _hasPageContextFromClient: boolean;
35
- } & {
36
- _hasPageContextFromServer: boolean;
37
- };
38
39
  is404ServerSideRouted?: undefined;
40
+ pageContextFromServerHooks: PageContextFromServerHooks;
39
41
  }>;
42
+ type PageContextFromClientHooks = {
43
+ _hasPageContextFromClient: boolean;
44
+ };
45
+ declare function getPageContextFromClientHooks(pageContext: {
46
+ pageId: string;
47
+ _hasPageContextFromServer: boolean;
48
+ } & PageContext & PageContextExports, isErrorPage: boolean): Promise<PageContextFromClientHooks>;
49
+ declare function setPageContextInitIsPassedToClient(pageContext: Record<string, unknown>): void;
@@ -1,6 +1,8 @@
1
1
  export { getPageContextFromHooks_isHydration };
2
- export { getPageContextFromHooks_isNotHydration };
3
2
  export { getPageContextFromHooks_serialized };
3
+ export { getPageContextFromServerHooks };
4
+ export { getPageContextFromClientHooks };
5
+ export { setPageContextInitIsPassedToClient };
4
6
  import { assert, assertUsage, hasProp, objectAssign, getProjectError, redirectHard, executeHook, isObject, getGlobalObject } from './utils.js';
5
7
  import { parse } from '@brillout/json-serializer/parse';
6
8
  import { getPageContextSerializedInHtml } from '../shared/getPageContextSerializedInHtml.js';
@@ -17,6 +19,7 @@ import { AbortRender, isAbortPageContext } from '../../shared/route/abort.js';
17
19
  import { pageContextInitIsPassedToClient } from '../../shared/misc/pageContextInitIsPassedToClient.js';
18
20
  import { isServerSideError } from '../../shared/misc/isServerSideError.js';
19
21
  const globalObject = getGlobalObject('router/getPageContext.ts', {});
22
+ // TODO/eventually: rename
20
23
  function getPageContextFromHooks_serialized() {
21
24
  const pageContextSerialized = getPageContextSerializedInHtml();
22
25
  assertUsage(!('urlOriginal' in pageContextSerialized), "Adding 'urlOriginal' to passToClient is forbidden");
@@ -26,28 +29,24 @@ function getPageContextFromHooks_serialized() {
26
29
  });
27
30
  return pageContextSerialized;
28
31
  }
32
+ // TODO/eventually: rename
29
33
  async function getPageContextFromHooks_isHydration(pageContext) {
30
34
  objectAssign(pageContext, {
31
- isHydration: true,
32
- _hasPageContextFromClient: false,
33
- _hasPageContextFromServer: true
35
+ _hasPageContextFromClient: false
34
36
  });
35
37
  for (const hookName of ['data', 'onBeforeRender']) {
36
38
  if (hookClientOnlyExists(hookName, pageContext)) {
37
39
  const pageContextFromHook = await executeHookClientSide(hookName, pageContext);
38
- if (pageContextFromHook)
39
- assert(!('urlOriginal' in pageContextFromHook));
40
+ assert(!('urlOriginal' in pageContextFromHook));
40
41
  Object.assign(pageContext, pageContextFromHook);
41
42
  }
42
43
  }
43
44
  return pageContext;
44
45
  }
45
- async function getPageContextFromHooks_isNotHydration(pageContext, isErrorPage) {
46
- objectAssign(pageContext, {
47
- isHydration: false,
48
- _hasPageContextFromClient: false
49
- });
50
- let hasPageContextFromServer = false;
46
+ async function getPageContextFromServerHooks(pageContext, isErrorPage) {
47
+ const pageContextFromServerHooks = {
48
+ _hasPageContextFromServer: false
49
+ };
51
50
  // If pageContextInit has some client data or if one of the hooks guard(), data() or onBeforeRender() is server-side
52
51
  // only, then we need to fetch pageContext from the server.
53
52
  // We do it before executing any client-side hook, because it contains pageContextInit which may be needed for guard() / data() / onBeforeRender(), for example pageContextInit.user is crucial for guard()
@@ -60,13 +59,19 @@ async function getPageContextFromHooks_isNotHydration(pageContext, isErrorPage)
60
59
  if ('is404ServerSideRouted' in res)
61
60
  return { is404ServerSideRouted: true };
62
61
  const { pageContextFromServer } = res;
63
- hasPageContextFromServer = true;
62
+ pageContextFromServerHooks._hasPageContextFromServer = true;
64
63
  // Already handled
65
64
  assert(!(isServerSideError in pageContextFromServer));
66
65
  assert(!('serverSideError' in pageContextFromServer));
67
- objectAssign(pageContext, pageContextFromServer);
66
+ objectAssign(pageContextFromServerHooks, pageContextFromServer);
68
67
  }
69
- objectAssign(pageContext, { _hasPageContextFromServer: hasPageContextFromServer });
68
+ // We cannot return the whole pageContext because this function is used for prefetching `pageContext` (which requires a partial pageContext to be merged with the future pageContext created upon rendering the page in the future).
69
+ return { pageContextFromServerHooks };
70
+ }
71
+ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
72
+ objectAssign(pageContext, {
73
+ _hasPageContextFromClient: false
74
+ });
70
75
  // At this point, we need to call the client-side guard(), data() and onBeforeRender() hooks, if they exist on client
71
76
  // env. However if we have fetched pageContext from the server, some of them might have run already on the
72
77
  // server-side, so we run only the client-only ones in this case.
@@ -76,7 +81,7 @@ async function getPageContextFromHooks_isNotHydration(pageContext, isErrorPage)
76
81
  if (hookName === 'guard') {
77
82
  if (!isErrorPage &&
78
83
  // We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the server-side.)
79
- !hasPageContextFromServer) {
84
+ !pageContext._hasPageContextFromServer) {
80
85
  // Should we really call the guard() hook on the client-side? Shouldn't we make the guard() hook a server-side
81
86
  // only hook? Or maybe make its env configurable like data() and onBeforeRender()?
82
87
  await executeGuardHook(pageContext, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
@@ -84,28 +89,22 @@ async function getPageContextFromHooks_isNotHydration(pageContext, isErrorPage)
84
89
  }
85
90
  else {
86
91
  assert(hookName === 'data' || hookName === 'onBeforeRender');
87
- if (hookClientOnlyExists(hookName, pageContext) || !hasPageContextFromServer) {
92
+ if (hookClientOnlyExists(hookName, pageContext) || !pageContext._hasPageContextFromServer) {
88
93
  // This won't do anything if no hook has been defined or if the hook's env.client is false.
89
94
  const pageContextFromHook = await executeHookClientSide(hookName, pageContext);
90
- if (pageContextFromHook)
91
- assert(!('urlOriginal' in pageContextFromHook));
95
+ assert(!('urlOriginal' in pageContextFromHook));
92
96
  Object.assign(pageContext, pageContextFromHook);
93
97
  }
94
- else {
95
- assert(hasPageContextFromServer);
96
- }
97
98
  }
98
99
  }
99
- objectAssign(pageContext, {
100
- _hasPageContextFromServer: hasPageContextFromServer
101
- });
102
- return { pageContextAugmented: pageContext };
100
+ const pageContextFromClientHooks = pageContext;
101
+ return pageContextFromClientHooks;
103
102
  }
104
103
  async function executeHookClientSide(hookName, pageContext) {
105
104
  const hook = getHook(pageContext, hookName);
106
105
  if (!hook) {
107
106
  // No hook defined or hook's env.client is false
108
- return null;
107
+ return {};
109
108
  }
110
109
  const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide(pageContext, true);
111
110
  const hookResult = await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook, pageContext);
@@ -165,9 +164,15 @@ async function hookServerOnlyExists(hookName, pageContext) {
165
164
  if (pageContext._pageConfigs.length > 0) {
166
165
  // V1
167
166
  const pageConfig = getPageConfig(pageContext.pageId, pageContext._pageConfigs);
168
- const hookEnv = getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value ?? {};
167
+ const hookEnv = getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value;
168
+ if (hookEnv === null)
169
+ return false;
169
170
  assert(isObject(hookEnv));
170
- return !!hookEnv.server && !hookEnv.client;
171
+ const { client, server } = hookEnv;
172
+ assert(client === true || client === undefined);
173
+ assert(server === true || server === undefined);
174
+ assert(client || server);
175
+ return !!server && !client;
171
176
  }
172
177
  else {
173
178
  // TODO/v1-release: remove
@@ -228,6 +233,5 @@ async function fetchPageContextFromServer(pageContext) {
228
233
  return { pageContextFromServer };
229
234
  }
230
235
  function processPageContextFromServer(pageContextFromServer) {
231
- setPageContextInitIsPassedToClient(pageContextFromServer);
232
236
  removeBuiltInOverrides(pageContextFromServer);
233
237
  }
@@ -4,7 +4,7 @@ import { assert, assertUsage, hasProp, isObject } from './utils.js';
4
4
  // - `history.state` can uninitialized (i.e. `null`):
5
5
  // - The very first render
6
6
  // - The user's code runs `location.hash = '#section'`
7
- // - The user clicks on an anchor link `<a href="#section">Section</a>` (Vike's `onLinkClick()` handler skips hash links).
7
+ // - The user clicks on an anchor link `<a href="#section">Section</a>` (Vike's `initOnLinkClick()` handler skips hash links).
8
8
  // - State information may be incomplete if `history.state` is set by an old Vike version. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
9
9
  function initHistoryState() {
10
10
  // No way found to add TypeScript types to `window.history.state`: https://github.com/microsoft/TypeScript/issues/36178
@@ -0,0 +1,2 @@
1
+ export { initClientRouter };
2
+ declare function initClientRouter(): Promise<void>;
@@ -1,22 +1,25 @@
1
- export { installClientRouter };
1
+ export { initClientRouter };
2
2
  import { assert } from './utils.js';
3
3
  import { initHistoryState, monkeyPatchHistoryPushState } from './history.js';
4
4
  import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
5
5
  import { onBrowserHistoryNavigation } from './onBrowserHistoryNavigation.js';
6
- import { onLinkClick } from './onLinkClick.js';
6
+ import { initOnLinkClick } from './initOnLinkClick.js';
7
7
  import { setupNativeScrollRestoration } from './scrollRestoration.js';
8
8
  import { autoSaveScrollPosition } from './setScrollPosition.js';
9
- async function installClientRouter() {
9
+ import { initLinkPrefetchHandlers } from './prefetch.js';
10
+ async function initClientRouter() {
10
11
  // Init navigation history and scroll restoration
11
12
  initHistoryAndScroll();
12
- // Render initial page
13
- const renderPromise = render();
13
+ // Render/hydrate
14
+ const renderFirstPagePromise = renderFirstPage();
14
15
  // Intercept <a> clicks
15
- onLinkClick();
16
+ initOnLinkClick();
17
+ // Add <a> prefetch handlers
18
+ initLinkPrefetchHandlers();
16
19
  // Preserve stack track
17
- await renderPromise;
20
+ await renderFirstPagePromise;
18
21
  }
19
- async function render() {
22
+ async function renderFirstPage() {
20
23
  assert(getRenderCount() === 0);
21
24
  await renderPageClientSide({
22
25
  scrollTarget: { preserveScroll: true },
@@ -0,0 +1,2 @@
1
+ export { initOnLinkClick };
2
+ declare function initOnLinkClick(): void;
@@ -1,9 +1,9 @@
1
1
  // Code adapted from https://github.com/HenrikJoreteg/internal-nav-helper/blob/5199ec5448d0b0db7ec63cf76d88fa6cad878b7d/src/index.js#L11-L29
2
- export { onLinkClick };
2
+ export { initOnLinkClick };
3
3
  import { assert } from './utils.js';
4
4
  import { skipLink } from './skipLink.js';
5
5
  import { renderPageClientSide } from './renderPageClientSide.js';
6
- function onLinkClick() {
6
+ function initOnLinkClick() {
7
7
  document.addEventListener('click', handler);
8
8
  }
9
9
  async function handler(ev) {
@@ -2,6 +2,7 @@ export { isClientSideRoutable };
2
2
  import { analyzePageClientSideInit } from '../../shared/getPageFiles/analyzePageClientSide.js';
3
3
  import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
4
4
  import { analyzeClientSide } from '../../shared/getPageFiles/analyzeClientSide.js';
5
+ // TODO/next-major-release: make it sync
5
6
  async function isClientSideRoutable(pageId, pageContext) {
6
7
  await analyzePageClientSideInit(pageContext._pageFilesAll, pageId, {
7
8
  sharedPageFilesAlreadyLoaded: false
@@ -1,7 +1,8 @@
1
1
  export { navigate };
2
2
  export { reload };
3
+ import { normalizeUrlArgument } from './normalizeUrlArgument.js';
3
4
  import { firstRenderStartPromise, renderPageClientSide } from './renderPageClientSide.js';
4
- import { assertClientRouting, assertUsageUrlPathname, getCurrentUrl } from './utils.js';
5
+ import { assertClientRouting, getCurrentUrl } from './utils.js';
5
6
  assertClientRouting();
6
7
  /** Programmatically navigate to a new page.
7
8
  *
@@ -12,7 +13,7 @@ assertClientRouting();
12
13
  * @param overwriteLastHistoryEntry - Don't create a new entry in the browser's history, instead let the new URL replace the current URL. (This effectively removes the current URL from the browser history).
13
14
  */
14
15
  async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryEntry = false } = {}) {
15
- assertUsageUrlPathname(url, '[navigate(url)] url');
16
+ normalizeUrlArgument(url, 'navigate');
16
17
  // If `hydrationCanBeAborted === false` (e.g. Vue) then we can apply navigate() only after hydration is done
17
18
  await firstRenderStartPromise;
18
19
  const scrollTarget = { preserveScroll: keepScrollPosition };
@@ -0,0 +1,2 @@
1
+ export { normalizeUrlArgument };
2
+ declare function normalizeUrlArgument(url: string, fnName: 'prefetch' | 'navigate'): string;
@@ -0,0 +1,14 @@
1
+ export { normalizeUrlArgument };
2
+ import { assertUsage, isUrl, isUrlPathnameRelative } from './utils.js';
3
+ function normalizeUrlArgument(url, fnName) {
4
+ // Succinct error message to save client-side KBs
5
+ const errMsg = `[${fnName}(url)] Invalid URL ${url}`;
6
+ assertUsage(isUrl(url), errMsg);
7
+ if (url.startsWith(location.origin)) {
8
+ url = url.slice(location.origin.length);
9
+ }
10
+ assertUsage(url.startsWith('/') || isUrlPathnameRelative(url),
11
+ // `errMsg` used the original `url` value
12
+ errMsg);
13
+ return url;
14
+ }
@@ -27,7 +27,7 @@ function onBrowserHistoryNavigation() {
27
27
  if (isHashNavigation && !isUserLandPushStateNavigation) {
28
28
  // - `history.state` is uninitialized (`null`) when:
29
29
  // - The user's code runs `window.location.hash = '#section'`.
30
- // - The user clicks on an anchor link `<a href="#section">Section</a>` (because Vike's `onLinkClick()` handler skips hash links).
30
+ // - The user clicks on an anchor link `<a href="#section">Section</a>` (because Vike's `initOnLinkClick()` handler skips hash links).
31
31
  // - `history.state` is `null` when uninitialized: https://developer.mozilla.org/en-US/docs/Web/API/History/state
32
32
  // - Alternatively, we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
33
33
  // - Problem: we cannot intercept `window.location.hash = '#section'`. (Or maybe we can with the `hashchange` event?)
@@ -0,0 +1,7 @@
1
+ export type { PrefetchStaticAssets };
2
+ export type { PrefetchSetting };
3
+ type PrefetchSetting = false | true | {
4
+ staticAssets?: false | 'hover' | 'viewport';
5
+ pageContext?: boolean | number;
6
+ };
7
+ type PrefetchStaticAssets = false | 'hover' | 'viewport';
@@ -1,9 +1,10 @@
1
1
  export { getPrefetchSettings };
2
- import type { PrefetchStaticAssets } from '../../../shared/types/PrefetchStaticAssets.js';
3
- type PageContextPrefetch = {
4
- exports: Record<string, unknown>;
2
+ export { PAGE_CONTEXT_MAX_AGE_DEFAULT };
3
+ export type { PrefetchSettingResolved };
4
+ import type { PageContextExports } from '../../../shared/getPageFiles.js';
5
+ declare const PAGE_CONTEXT_MAX_AGE_DEFAULT = 5000;
6
+ type PrefetchSettingResolved = {
7
+ staticAssets: false | 'hover' | 'viewport';
8
+ pageContext: false | number;
5
9
  };
6
- type PrefetchSettings = {
7
- prefetchStaticAssets: PrefetchStaticAssets;
8
- };
9
- declare function getPrefetchSettings(pageContext: PageContextPrefetch, linkTag: HTMLElement): PrefetchSettings;
10
+ declare function getPrefetchSettings(pageContext: PageContextExports, linkTag: null | HTMLElement): PrefetchSettingResolved;
@@ -1,82 +1,90 @@
1
+ // TODO/pageContext-prefetch: rename this file to getPrefetchSettingResolved.ts
1
2
  export { getPrefetchSettings };
2
- import { assert, assertUsage, assertInfo, assertWarning, isPlainObject } from '../utils.js';
3
+ export { PAGE_CONTEXT_MAX_AGE_DEFAULT };
4
+ import { assertUsage, assertInfo } from '../utils.js';
5
+ // TODO/pageContext-prefetch: Make it `Infinity` for pre-rendered pages.
6
+ const PAGE_CONTEXT_MAX_AGE_DEFAULT = 5000;
7
+ const prefetchSettingTrue = {
8
+ staticAssets: 'hover',
9
+ pageContext: PAGE_CONTEXT_MAX_AGE_DEFAULT
10
+ };
11
+ const prefetchSettingFalse = {
12
+ staticAssets: 'hover',
13
+ pageContext: false
14
+ };
15
+ // TODO/v1-release: change to `prefetchSettingTrue`?
16
+ const prefetchSettingDefault = prefetchSettingFalse;
3
17
  function getPrefetchSettings(pageContext, linkTag) {
4
- let prefetchStaticAssets = getPrefetchStaticAssets(pageContext, linkTag);
5
- if (prefetchStaticAssets === 'viewport' && import.meta.env.DEV) {
6
- assertInfo(false, 'Viewport prefetching is disabled in development', { onlyOnce: true });
7
- prefetchStaticAssets = 'hover';
8
- }
9
- return {
10
- prefetchStaticAssets
11
- };
12
- }
13
- function getPrefetchStaticAssets(pageContext, linkTag) {
14
- {
15
- const prefetchAttribute = getPrefetchAttribute(linkTag);
16
- if (prefetchAttribute !== null)
17
- return prefetchAttribute;
18
- }
18
+ let prefetchSetting = prefetchSettingDefault;
19
19
  // TODO/v1-release: remove
20
20
  if ('prefetchLinks' in pageContext.exports) {
21
21
  assertUsage(false, '`export { prefetchLinks }` is deprecated, use `export { prefetchStaticAssets }` instead.');
22
22
  }
23
+ // TODO/v1-release: remove
23
24
  if ('prefetchStaticAssets' in pageContext.exports) {
24
- const { prefetchStaticAssets } = pageContext.exports;
25
- if (prefetchStaticAssets === false) {
26
- return false;
27
- }
28
- if (prefetchStaticAssets === 'hover') {
29
- return 'hover';
30
- }
31
- if (prefetchStaticAssets === 'viewport') {
32
- return 'viewport';
33
- }
34
- const wrongUsageMsg = "prefetchStaticAssets value should be false, 'hover', or 'viewport'";
35
- // TODO/v1-release: remove
36
- assertUsage(isPlainObject(prefetchStaticAssets), wrongUsageMsg);
37
- const keys = Object.keys(prefetchStaticAssets);
38
- assertUsage(keys.length === 1 && keys[0] === 'when', wrongUsageMsg);
39
- const { when } = prefetchStaticAssets;
40
- if (when === 'HOVER' || when === 'VIEWPORT') {
41
- const correctValue = when.toLowerCase();
42
- assertWarning(false, `prefetchStaticAssets value \`{ when: '${when}' }\` is outdated: set prefetchStaticAssets to '${correctValue}' instead`, { onlyOnce: true });
43
- return correctValue;
25
+ const prefetchStaticAssets = pageContext.exports.prefetchStaticAssets;
26
+ /* TODO/pageContext-prefetch: uncomment
27
+ const msg = `The 'prefetchStaticAssets' setting is deprecated in favor of the 'prefetch' setting, see https://vike.dev/prefetch`
28
+ assertWarning(false, msg, { onlyOnce: true })
29
+ assertUsage(
30
+ prefetchStaticAssets === false || prefetchStaticAssets === 'hover' || prefetchStaticAssets === 'viewport',
31
+ msg
32
+ )
33
+ //*/
34
+ prefetchSetting.staticAssets = prefetchStaticAssets;
35
+ }
36
+ if ('prefetch' in pageContext.exports) {
37
+ const { prefetch } = pageContext.exports;
38
+ if (prefetch === true)
39
+ prefetchSetting = prefetchSettingTrue;
40
+ if (prefetch === false)
41
+ prefetchSetting = prefetchSettingFalse;
42
+ // No validation in order to save client-side KBs
43
+ Object.assign(prefetchSetting, prefetch);
44
+ if (prefetchSetting.pageContext === true) {
45
+ prefetchSetting.pageContext = PAGE_CONTEXT_MAX_AGE_DEFAULT;
44
46
  }
45
- assertUsage(false, wrongUsageMsg);
46
47
  }
47
- return 'hover';
48
- }
49
- function getPrefetchAttribute(linkTag) {
50
- const attr = linkTag.getAttribute('data-prefetch-static-assets');
51
- const attrOld = linkTag.getAttribute('data-prefetch');
52
- if (attr === null && attrOld === null) {
53
- return null;
48
+ if (prefetchSetting.staticAssets === 'viewport' && import.meta.env.DEV) {
49
+ assertInfo(false, 'Viewport prefetching is disabled in development', { onlyOnce: true });
50
+ prefetchSetting.staticAssets = 'hover';
54
51
  }
55
- // TODO/v1-release: remove
56
- const deprecationNotice = 'The attribute data-prefetch is outdated, use data-prefetch-static-assets instead.';
57
- if (attr) {
58
- assertUsage(attrOld === null, deprecationNotice);
59
- if (attr === 'hover' || attr === 'viewport') {
60
- return attr;
52
+ if (linkTag) {
53
+ {
54
+ let attr = linkTag.getAttribute('data-prefetch');
55
+ if (attr !== null) {
56
+ if (attr === '')
57
+ attr = 'true';
58
+ if (attr === 'true')
59
+ prefetchSetting = prefetchSettingTrue;
60
+ if (attr === 'false')
61
+ prefetchSetting = prefetchSettingFalse;
62
+ }
61
63
  }
62
- if (attr === 'false') {
63
- return false;
64
- }
65
- assertUsage(false, `data-prefetch-static-assets has value "${attr}" but it should instead be "false", "hover", or "viewport"`);
66
- }
67
- // TODO/v1-release: remove
68
- if (attrOld) {
69
- assert(!attr);
70
- assertWarning(false, deprecationNotice, {
71
- onlyOnce: true
72
- });
73
- if (attrOld === 'true') {
74
- return 'viewport';
64
+ {
65
+ let attr = linkTag.getAttribute('data-prefetch-static-assets');
66
+ if (attr !== null) {
67
+ if (attr === 'false')
68
+ prefetchSetting.staticAssets = false;
69
+ // No validation in order to save client-side KBs
70
+ prefetchSetting.staticAssets = attr;
71
+ }
75
72
  }
76
- if (attrOld === 'false') {
77
- return 'hover';
73
+ {
74
+ let attr = linkTag.getAttribute('data-prefetch-page-context');
75
+ if (attr !== null) {
76
+ if (attr === '')
77
+ attr = 'true';
78
+ if (attr === 'true')
79
+ prefetchSetting.pageContext = PAGE_CONTEXT_MAX_AGE_DEFAULT;
80
+ if (attr === 'false')
81
+ prefetchSetting.pageContext = false;
82
+ const n = parseInt(attr, 10);
83
+ if (!Number.isNaN(n))
84
+ prefetchSetting.pageContext = n;
85
+ // No validation in order to save client-side KBs
86
+ }
78
87
  }
79
- assertUsage(false, `data-prefetch has value "${attrOld}" but it should instead be "true" or "false"`);
80
88
  }
81
- assert(false);
89
+ return prefetchSetting;
82
90
  }
@@ -1,5 +1,26 @@
1
1
  export { prefetch };
2
+ export { getPageContextPrefetched };
3
+ export { initLinkPrefetchHandlers };
4
+ export { populatePageContextPrefetchCache };
2
5
  export { addLinkPrefetchHandlers };
6
+ export { addLinkPrefetchHandlers_watch };
7
+ export { addLinkPrefetchHandlers_unwatch };
8
+ import { type PageContextFromServerHooks, getPageContextFromServerHooks } from './getPageContextFromHooks.js';
9
+ import type { PageContextExports, PageFile } from '../../shared/getPageFiles.js';
10
+ import { type PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
11
+ type ResultPageContextFromServer = Awaited<ReturnType<typeof getPageContextFromServerHooks>>;
12
+ type PageContextForPrefetch = {
13
+ urlOriginal: string;
14
+ urlPathname: string;
15
+ pageId: string;
16
+ _urlRewrite: null;
17
+ _pageFilesAll: PageFile[];
18
+ _pageConfigs: PageConfigRuntime[];
19
+ };
20
+ declare function getPageContextPrefetched(pageContext: {
21
+ urlPathname: string;
22
+ } & PageContextExports): null | PageContextFromServerHooks;
23
+ declare function populatePageContextPrefetchCache(pageContext: PageContextForPrefetch, result: ResultPageContextFromServer): void;
3
24
  /**
4
25
  * Programmatically prefetch client assets.
5
26
  *
@@ -7,8 +28,11 @@ export { addLinkPrefetchHandlers };
7
28
  *
8
29
  * @param url - The URL of the page you want to prefetch.
9
30
  */
10
- declare function prefetch(url: string): Promise<void>;
11
- declare function addLinkPrefetchHandlers(pageContext: {
12
- exports: Record<string, unknown>;
13
- urlPathname: string;
14
- }): void;
31
+ declare function prefetch(url: string, options?: {
32
+ pageContext?: boolean;
33
+ staticAssets?: boolean;
34
+ }): Promise<void>;
35
+ declare function addLinkPrefetchHandlers(): void;
36
+ declare function initLinkPrefetchHandlers(): void;
37
+ declare function addLinkPrefetchHandlers_watch(): void;
38
+ declare function addLinkPrefetchHandlers_unwatch(): void;