vike 0.4.144 → 0.4.145-commit-2520555

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 (198) hide show
  1. package/dist/cjs/__internal/index.js +6 -2
  2. package/dist/cjs/node/plugin/plugins/buildConfig.js +3 -3
  3. package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
  4. package/dist/cjs/node/plugin/plugins/config/index.js +3 -3
  5. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +8 -8
  6. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
  7. package/dist/cjs/node/plugin/plugins/envVars.js +34 -20
  8. package/dist/cjs/node/plugin/plugins/importBuild/index.js +3 -3
  9. package/dist/cjs/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
  10. package/dist/cjs/node/plugin/plugins/importUserCode/index.js +3 -3
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +249 -228
  14. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +8 -6
  15. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +36 -14
  16. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  17. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +18 -0
  18. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +15 -17
  19. package/dist/cjs/node/plugin/plugins/previewConfig.js +11 -2
  20. package/dist/cjs/node/prerender/runPrerender.js +34 -26
  21. package/dist/cjs/node/prerender/utils.js +1 -1
  22. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +20 -6
  23. package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +5 -5
  24. package/dist/cjs/node/runtime/renderPage/log404/index.js +28 -17
  25. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -3
  26. package/dist/cjs/node/runtime/renderPage.js +3 -3
  27. package/dist/cjs/node/runtime/utils.js +1 -1
  28. package/dist/cjs/node/shared/getClientEntryFilePath.js +2 -2
  29. package/dist/cjs/node/shared/getConfigVike.js +4 -1
  30. package/dist/cjs/shared/addUrlComputedProps.js +24 -12
  31. package/dist/cjs/shared/getPageFiles/analyzeClientSide.js +4 -6
  32. package/dist/cjs/shared/getPageFiles/getExports.js +3 -3
  33. package/dist/cjs/shared/hooks/getHook.js +1 -1
  34. package/dist/cjs/shared/page-configs/getExportPath.js +3 -3
  35. package/dist/cjs/shared/page-configs/helpers/getConfigDefinedAtString.js +43 -0
  36. package/dist/cjs/shared/page-configs/helpers/getConfigValue.js +44 -0
  37. package/dist/cjs/shared/page-configs/helpers.js +33 -0
  38. package/dist/cjs/shared/page-configs/loadConfigValues.js +2 -2
  39. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +14 -13
  40. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  41. package/dist/cjs/shared/page-configs/serialize/serializeConfigValue.js +9 -10
  42. package/dist/cjs/shared/route/abort.js +1 -1
  43. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +41 -15
  44. package/dist/cjs/shared/route/index.js +22 -32
  45. package/dist/cjs/shared/route/loadPageRoutes.js +11 -10
  46. package/dist/cjs/shared/route/noRouteMatch.js +4 -0
  47. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
  48. package/dist/cjs/shared/utils.js +1 -1
  49. package/dist/cjs/utils/getFilePathAbsolute.js +11 -11
  50. package/dist/cjs/utils/isExternalLink.js +7 -0
  51. package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
  52. package/dist/cjs/utils/onPageVisibilityChange.js +19 -0
  53. package/dist/cjs/utils/parseUrl.js +1 -1
  54. package/dist/cjs/utils/projectInfo.js +1 -1
  55. package/dist/cjs/utils/truncateString.js +12 -7
  56. package/dist/esm/__internal/index.d.ts +6 -3
  57. package/dist/esm/__internal/index.js +8 -3
  58. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
  59. package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -4
  60. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  61. package/dist/esm/client/client-routing-runtime/getBaseServer.d.ts +2 -1
  62. package/dist/esm/client/client-routing-runtime/getBaseServer.js +2 -1
  63. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +39 -0
  64. package/dist/esm/client/client-routing-runtime/{getPageContext.js → getPageContextFromHooks.js} +50 -79
  65. package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
  66. package/dist/esm/client/client-routing-runtime/history.js +31 -9
  67. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +2 -0
  68. package/dist/esm/client/client-routing-runtime/installClientRouter.js +22 -0
  69. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
  70. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +12 -0
  71. package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
  72. package/dist/esm/client/client-routing-runtime/navigate.js +9 -8
  73. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +4 -0
  74. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +63 -0
  75. package/dist/esm/client/client-routing-runtime/onLinkClick.d.ts +2 -0
  76. package/dist/esm/client/client-routing-runtime/onLinkClick.js +40 -0
  77. package/dist/esm/client/client-routing-runtime/prefetch.js +54 -29
  78. package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +19 -0
  79. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +347 -0
  80. package/dist/esm/client/client-routing-runtime/scrollRestoration.d.ts +6 -0
  81. package/dist/esm/client/client-routing-runtime/scrollRestoration.js +25 -0
  82. package/dist/esm/client/client-routing-runtime/setScrollPosition.d.ts +7 -0
  83. package/dist/esm/client/client-routing-runtime/setScrollPosition.js +77 -0
  84. package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
  85. package/dist/esm/client/client-routing-runtime/skipLink.js +9 -5
  86. package/dist/esm/client/client-routing-runtime/utils.d.ts +2 -0
  87. package/dist/esm/client/client-routing-runtime/utils.js +2 -0
  88. package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
  89. package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
  90. package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
  91. package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +8 -3
  92. package/dist/esm/client/shared/loadPageFilesClientSide.js +5 -5
  93. package/dist/esm/node/plugin/plugins/buildConfig.js +3 -3
  94. package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
  95. package/dist/esm/node/plugin/plugins/config/index.js +4 -4
  96. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +9 -9
  97. package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
  98. package/dist/esm/node/plugin/plugins/envVars.d.ts +2 -0
  99. package/dist/esm/node/plugin/plugins/envVars.js +35 -20
  100. package/dist/esm/node/plugin/plugins/importBuild/index.js +3 -3
  101. package/dist/esm/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
  102. package/dist/esm/node/plugin/plugins/importUserCode/index.js +3 -3
  103. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +2 -1
  104. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
  105. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +1 -1
  106. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
  107. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +2 -1
  108. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +250 -229
  109. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.d.ts +2 -2
  110. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +7 -5
  111. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +2 -2
  112. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +37 -15
  113. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  114. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.d.ts +7 -0
  115. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +15 -0
  116. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.d.ts +2 -2
  117. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +16 -18
  118. package/dist/esm/node/plugin/plugins/previewConfig.js +11 -2
  119. package/dist/esm/node/prerender/runPrerender.js +29 -21
  120. package/dist/esm/node/prerender/utils.d.ts +1 -1
  121. package/dist/esm/node/prerender/utils.js +1 -1
  122. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +21 -7
  123. package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +5 -5
  124. package/dist/esm/node/runtime/renderPage/debugPageFiles.js +5 -5
  125. package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
  126. package/dist/esm/node/runtime/renderPage/log404/index.d.ts +2 -2
  127. package/dist/esm/node/runtime/renderPage/log404/index.js +28 -16
  128. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -2
  129. package/dist/esm/node/runtime/renderPage.js +3 -3
  130. package/dist/esm/node/runtime/utils.d.ts +1 -1
  131. package/dist/esm/node/runtime/utils.js +1 -1
  132. package/dist/esm/node/shared/getClientEntryFilePath.js +1 -1
  133. package/dist/esm/node/shared/getConfigVike.d.ts +2 -1
  134. package/dist/esm/node/shared/getConfigVike.js +4 -1
  135. package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
  136. package/dist/esm/shared/addUrlComputedProps.js +25 -13
  137. package/dist/esm/shared/getPageFiles/analyzeClientSide.js +2 -4
  138. package/dist/esm/shared/getPageFiles/getExports.js +2 -2
  139. package/dist/esm/shared/hooks/getHook.js +1 -1
  140. package/dist/esm/shared/page-configs/PageConfig.d.ts +55 -31
  141. package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
  142. package/dist/esm/shared/page-configs/getExportPath.js +3 -3
  143. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.d.ts +7 -0
  144. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.js +37 -0
  145. package/dist/esm/shared/page-configs/helpers/getConfigValue.d.ts +14 -0
  146. package/dist/esm/shared/page-configs/helpers/getConfigValue.js +38 -0
  147. package/dist/esm/shared/page-configs/helpers.d.ts +13 -0
  148. package/dist/esm/shared/page-configs/helpers.js +27 -0
  149. package/dist/esm/shared/page-configs/loadConfigValues.js +2 -2
  150. package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.d.ts +4 -4
  151. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +15 -11
  152. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  153. package/dist/esm/shared/page-configs/serialize/serializeConfigValue.js +9 -10
  154. package/dist/esm/shared/route/abort.js +1 -1
  155. package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
  156. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +41 -15
  157. package/dist/esm/shared/route/index.d.ts +12 -10
  158. package/dist/esm/shared/route/index.js +23 -33
  159. package/dist/esm/shared/route/loadPageRoutes.js +8 -7
  160. package/dist/esm/shared/route/noRouteMatch.d.ts +1 -0
  161. package/dist/esm/shared/route/noRouteMatch.js +1 -0
  162. package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
  163. package/dist/esm/shared/utils.d.ts +1 -1
  164. package/dist/esm/shared/utils.js +1 -1
  165. package/dist/esm/utils/getFilePathAbsolute.d.ts +1 -1
  166. package/dist/esm/utils/getFilePathAbsolute.js +11 -11
  167. package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
  168. package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
  169. package/dist/esm/utils/onPageVisibilityChange.d.ts +4 -0
  170. package/dist/esm/utils/onPageVisibilityChange.js +16 -0
  171. package/dist/esm/utils/parseUrl.js +1 -1
  172. package/dist/esm/utils/projectInfo.d.ts +1 -1
  173. package/dist/esm/utils/projectInfo.js +1 -1
  174. package/dist/esm/utils/truncateString.d.ts +2 -1
  175. package/dist/esm/utils/truncateString.js +10 -7
  176. package/node/cli/bin-entry.js +1 -1
  177. package/package.json +2 -3
  178. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -16
  179. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -13
  180. package/dist/cjs/shared/page-configs/utils.js +0 -103
  181. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -29
  182. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +0 -10
  183. package/dist/esm/client/client-routing-runtime/getPageId.js +0 -17
  184. package/dist/esm/client/client-routing-runtime/navigationState.d.ts +0 -5
  185. package/dist/esm/client/client-routing-runtime/navigationState.js +0 -14
  186. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
  187. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
  188. package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
  189. package/dist/esm/client/client-routing-runtime/useClientRouter.js +0 -493
  190. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.d.ts +0 -24
  191. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -13
  192. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.d.ts +0 -3
  193. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -10
  194. package/dist/esm/shared/page-configs/utils.d.ts +0 -35
  195. package/dist/esm/shared/page-configs/utils.js +0 -97
  196. package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
  197. /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.d.ts +0 -0
  198. /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.js +0 -0
@@ -1,105 +1,91 @@
1
- export { getPageContext };
2
- export { getPageContextErrorPage };
3
- export { checkIf404 };
1
+ export { getPageContextFromHooks_firstRender };
2
+ export { getPageContextFromHooks_uponNavigation };
3
+ export { getPageContextFromHooks_errorPage };
4
4
  export { isAlreadyServerSideRouted };
5
- import { navigationState } from './navigationState.js';
6
5
  import { assert, assertUsage, hasProp, objectAssign, getProjectError, serverSideRouteTo, executeHook, isObject, getGlobalObject } from './utils.js';
7
6
  import { parse } from '@brillout/json-serializer/parse';
8
7
  import { getPageContextSerializedInHtml } from '../shared/getPageContextSerializedInHtml.js';
9
8
  import { analyzePageServerSide } from '../../shared/getPageFiles/analyzePageServerSide.js';
10
- import { route } from '../../shared/route/index.js';
11
9
  import { getErrorPageId } from '../../shared/error-page.js';
12
10
  import { getHook } from '../../shared/hooks/getHook.js';
13
11
  import { preparePageContextForUserConsumptionClientSide } from '../shared/preparePageContextForUserConsumptionClientSide.js';
14
12
  import { loadPageFilesClientSide } from '../shared/loadPageFilesClientSide.js';
15
13
  import { removeBuiltInOverrides } from './getPageContext/removeBuiltInOverrides.js';
16
14
  import { getPageContextRequestUrl } from '../../shared/getPageContextRequestUrl.js';
17
- import { getConfigValue, getPageConfig } from '../../shared/page-configs/utils.js';
15
+ import { getConfigValue, getPageConfig } from '../../shared/page-configs/helpers.js';
18
16
  import { assertOnBeforeRenderHookReturn } from '../../shared/assertOnBeforeRenderHookReturn.js';
19
17
  import { executeGuardHook } from '../../shared/route/executeGuardHook.js';
20
18
  import { AbortRender, isAbortPageContext } from '../../shared/route/abort.js';
21
19
  const globalObject = getGlobalObject('router/getPageContext.ts', {});
22
- async function getPageContext(pageContext) {
23
- if (pageContext._isFirstRenderAttempt && navigationState.isFirstUrl(pageContext.urlOriginal)) {
24
- assert(hasProp(pageContext, '_isFirstRenderAttempt', 'true'));
25
- const pageContextAddendum = await getPageContextFirstRender(pageContext);
26
- setPageContextInitHasClientData(pageContextAddendum);
27
- return pageContextAddendum;
28
- }
29
- else {
30
- assert(hasProp(pageContext, '_isFirstRenderAttempt', 'false'));
31
- const pageContextAddendum = await getPageContextUponNavigation(pageContext);
32
- setPageContextInitHasClientData(pageContextAddendum);
33
- return pageContextAddendum;
34
- }
35
- }
36
- async function getPageContextFirstRender(pageContext) {
37
- const pageContextAddendum = getPageContextSerializedInHtml();
38
- removeBuiltInOverrides(pageContextAddendum);
39
- objectAssign(pageContextAddendum, {
20
+ async function getPageContextFromHooks_firstRender(pageContext) {
21
+ const pageContextFromHooks = getPageContextSerializedInHtml();
22
+ removeBuiltInOverrides(pageContextFromHooks);
23
+ objectAssign(pageContextFromHooks, {
40
24
  isHydration: true,
41
25
  _hasPageContextFromClient: false
42
26
  });
43
- objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContext._pageFilesAll, pageContext._pageConfigs, pageContextAddendum._pageId));
27
+ objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
44
28
  {
45
- const pageContextForHook = { ...pageContext, ...pageContextAddendum };
29
+ const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
46
30
  if (await onBeforeRenderClientOnlyExists(pageContextForHook)) {
47
31
  const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
48
- objectAssign(pageContextAddendum, pageContextFromHook);
32
+ objectAssign(pageContextFromHooks, pageContextFromHook);
49
33
  }
50
34
  }
51
- return pageContextAddendum;
35
+ setPageContextInitHasClientData(pageContextFromHooks);
36
+ return pageContextFromHooks;
52
37
  }
53
- async function getPageContextErrorPage(pageContext) {
38
+ async function getPageContextFromHooks_errorPage(pageContext) {
54
39
  const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
55
40
  if (!errorPageId)
56
41
  throw new Error('No error page defined.');
57
- const pageContextAddendum = {
42
+ const pageContextFromHooks = {
58
43
  isHydration: false,
59
44
  _pageId: errorPageId
60
45
  };
61
- objectAssign(pageContextAddendum, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextAddendum }, true));
62
- return pageContextAddendum;
46
+ objectAssign(pageContextFromHooks, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextFromHooks }, true));
47
+ return pageContextFromHooks;
63
48
  }
64
- async function getPageContextUponNavigation(pageContext) {
65
- const pageContextAddendum = {
66
- isHydration: false
49
+ async function getPageContextFromHooks_uponNavigation(pageContext) {
50
+ const pageContextFromHooks = {
51
+ isHydration: false,
52
+ _pageId: pageContext._pageId
67
53
  };
68
- objectAssign(pageContextAddendum, await getPageContextFromRoute(pageContext));
69
- objectAssign(pageContextAddendum, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextAddendum }, false));
70
- return pageContextAddendum;
54
+ objectAssign(pageContextFromHooks, await getPageContextAlreadyRouted({ ...pageContext, ...pageContextFromHooks }, false));
55
+ setPageContextInitHasClientData(pageContextFromHooks);
56
+ return pageContextFromHooks;
71
57
  }
72
58
  async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
73
- let pageContextAddendum = {};
74
- objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContext._pageFilesAll, pageContext._pageConfigs, pageContext._pageId));
59
+ let pageContextFromHooks = {};
60
+ objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
75
61
  // Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
76
62
  if (
77
63
  // For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
78
64
  !isErrorPage &&
79
- (await hasPageContextServer({ ...pageContext, ...pageContextAddendum }))) {
65
+ (await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
80
66
  const pageContextFromServer = await fetchPageContextFromServer(pageContext);
81
67
  if (!pageContextFromServer['_isError']) {
82
- objectAssign(pageContextAddendum, pageContextFromServer);
68
+ objectAssign(pageContextFromHooks, pageContextFromServer);
83
69
  }
84
70
  else {
85
71
  const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
86
72
  assert(errorPageId);
87
- pageContextAddendum = {};
88
- objectAssign(pageContextAddendum, {
73
+ pageContextFromHooks = {};
74
+ objectAssign(pageContextFromHooks, {
89
75
  isHydration: false,
90
76
  _pageId: errorPageId
91
77
  });
92
- objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContext._pageFilesAll, pageContext._pageConfigs, pageContextAddendum._pageId));
78
+ objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
93
79
  assert(hasProp(pageContextFromServer, 'is404', 'boolean'));
94
80
  assert(hasProp(pageContextFromServer, 'pageProps', 'object'));
95
81
  assert(hasProp(pageContextFromServer.pageProps, 'is404', 'boolean'));
96
82
  // When the user hasn't define a `_error.page.js` file: the mechanism with `serverSideError: true` is used instead
97
83
  assert(!('serverSideError' in pageContextFromServer));
98
- objectAssign(pageContextAddendum, pageContextFromServer);
84
+ objectAssign(pageContextFromHooks, pageContextFromServer);
99
85
  }
100
86
  }
101
87
  else {
102
- objectAssign(pageContextAddendum, { _hasPageContextFromServer: false });
88
+ objectAssign(pageContextFromHooks, { _hasPageContextFromServer: false });
103
89
  // 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 serve-side.)
104
90
  // We cannot call guard() before retrieving pageContext from server, since the server-side may define pageContextInit.user which is paramount for guard() hooks
105
91
  if (!isErrorPage) {
@@ -107,41 +93,41 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
107
93
  await executeGuardHook({
108
94
  _hasPageContextFromClient: false,
109
95
  ...pageContext,
110
- ...pageContextAddendum
96
+ ...pageContextFromHooks
111
97
  }, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
112
98
  }
113
99
  }
114
100
  {
115
101
  // For the error page, we also execute the client-side onBeforeRender() hook, but maybe we shouldn't? The server-side does it as well (but maybe it shouldn't).
116
- const pageContextFromHook = await executeOnBeforeRenderHookClientSide({ ...pageContext, ...pageContextAddendum });
117
- objectAssign(pageContextAddendum, pageContextFromHook);
102
+ const pageContextFromOnBeforeRender = await executeOnBeforeRenderHookClientSide({
103
+ ...pageContext,
104
+ ...pageContextFromHooks
105
+ });
106
+ objectAssign(pageContextFromHooks, pageContextFromOnBeforeRender);
118
107
  }
119
- return pageContextAddendum;
108
+ return pageContextFromHooks;
120
109
  }
121
110
  async function executeOnBeforeRenderHookClientSide(pageContext) {
122
111
  const hook = getHook(pageContext, 'onBeforeRender');
123
112
  if (!hook) {
124
- const pageContextAddendum = {
113
+ const pageContextFromOnBeforeRender = {
125
114
  _hasPageContextFromClient: false
126
115
  };
127
- return pageContextAddendum;
116
+ return pageContextFromOnBeforeRender;
128
117
  }
129
118
  const onBeforeRender = hook.hookFn;
130
- const pageContextAddendum = {
119
+ const pageContextFromOnBeforeRender = {
131
120
  _hasPageContextFromClient: true
132
121
  };
133
122
  const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide({
134
123
  ...pageContext,
135
- ...pageContextAddendum
124
+ ...pageContextFromOnBeforeRender
136
125
  }, true);
137
126
  const hookResult = await executeHook(() => onBeforeRender(pageContextForUserConsumption), 'onBeforeRender', hook.hookFilePath);
138
127
  assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
139
128
  const pageContextFromHook = hookResult?.pageContext;
140
- objectAssign(pageContextAddendum, pageContextFromHook);
141
- return pageContextAddendum;
142
- }
143
- async function hasPageContextServer(pageContext) {
144
- return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
129
+ objectAssign(pageContextFromOnBeforeRender, pageContextFromHook);
130
+ return pageContextFromOnBeforeRender;
145
131
  }
146
132
  // Workaround for the fact that the client-side cannot known whether a pageContext JSON request is needed in order to fetch pageContextInit data passed to the client.
147
133
  // - The workaround is reliable as long as the user sets additional pageContextInit to undefined instead of not defining the property:
@@ -160,6 +146,9 @@ function setPageContextInitHasClientData(pageContext) {
160
146
  globalObject.pageContextInitHasClientData = true;
161
147
  }
162
148
  }
149
+ async function hasPageContextServer(pageContext) {
150
+ return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
151
+ }
163
152
  async function onBeforeRenderServerOnlyExists(pageContext) {
164
153
  if (pageContext._pageConfigs.length > 0) {
165
154
  // V1
@@ -184,26 +173,8 @@ async function onBeforeRenderClientOnlyExists(pageContext) {
184
173
  return false;
185
174
  }
186
175
  }
187
- async function getPageContextFromRoute(pageContext) {
188
- const routeResult = await route(pageContext);
189
- const pageContextFromRoute = routeResult.pageContextAddendum;
190
- if (!pageContextFromRoute._pageId) {
191
- const err = new Error('No routing match');
192
- markIs404(err);
193
- throw err;
194
- }
195
- assert(hasProp(pageContextFromRoute, '_pageId', 'string'));
196
- return pageContextFromRoute;
197
- }
198
- function markIs404(err) {
199
- objectAssign(err, { _is404: true });
200
- }
201
- function checkIf404(err) {
202
- return isObject(err) && err._is404 === true;
203
- }
204
176
  async function fetchPageContextFromServer(pageContext) {
205
- const urlLogical = pageContext._urlRewrite ?? pageContext._urlOriginalPristine ?? pageContext.urlOriginal;
206
- const pageContextUrl = getPageContextRequestUrl(urlLogical);
177
+ const pageContextUrl = getPageContextRequestUrl(pageContext._urlRewrite ?? pageContext.urlOriginal);
207
178
  const response = await fetch(pageContextUrl);
208
179
  {
209
180
  const contentType = response.headers.get('content-type');
@@ -1,7 +1,8 @@
1
- export { initHistoryState, getHistoryState, pushHistory, ScrollPosition, saveScrollPosition };
1
+ export { initHistoryState, getHistoryState, pushHistory, ScrollPosition, saveScrollPosition, monkeyPatchHistoryPushState };
2
2
  type HistoryState = {
3
3
  timestamp?: number;
4
4
  scrollPosition?: null | ScrollPosition;
5
+ triggedBy?: 'user' | 'vike' | 'browser';
5
6
  };
6
7
  type ScrollPosition = {
7
8
  x: number;
@@ -11,3 +12,4 @@ declare function initHistoryState(): void;
11
12
  declare function getHistoryState(): HistoryState;
12
13
  declare function saveScrollPosition(): void;
13
14
  declare function pushHistory(url: string, overwriteLastHistoryEntry: boolean): void;
15
+ declare function monkeyPatchHistoryPushState(): void;
@@ -1,10 +1,12 @@
1
- export { initHistoryState, getHistoryState, pushHistory, saveScrollPosition };
2
- import { assert, hasProp, isObject } from './utils.js';
3
- // Fill missing state information.
4
- // - The very first render => `history.state` is uninitialized (`null`).
5
- // - The vike app runs `location.hash = '#section'` => `history.state` is uninitialized (`null`).
6
- // - The user clicks on an anchor link `<a href="#section">Section</a>` => `history.state` is uninitialized (`null`).
7
- // - `history.state` set by an old vike version => state information may be incomplete. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
1
+ export { initHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
2
+ import { assert, assertUsage, getGlobalObject, hasProp, isObject } from './utils.js';
3
+ const globalObject = getGlobalObject('history.ts', {});
4
+ // Fill missing state information:
5
+ // - `history.state` can uninitialized (i.e. `null`):
6
+ // - The very first render
7
+ // - The user's code runs `location.hash = '#section'`
8
+ // - The user clicks on an anchor link `<a href="#section">Section</a>` (Vike's `onLinkClick()` handler skips hash links).
9
+ // - 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`.)
8
10
  function initHistoryState() {
9
11
  let state = window.history.state;
10
12
  if (!state) {
@@ -19,6 +21,9 @@ function initHistoryState() {
19
21
  hasModifications = true;
20
22
  state.scrollPosition = getScrollPosition();
21
23
  }
24
+ if (!('triggedBy' in state)) {
25
+ state.triggedBy = 'browser';
26
+ }
22
27
  assertState(state);
23
28
  if (hasModifications) {
24
29
  replaceHistoryState(state);
@@ -44,7 +49,7 @@ function saveScrollPosition() {
44
49
  function pushHistory(url, overwriteLastHistoryEntry) {
45
50
  if (!overwriteLastHistoryEntry) {
46
51
  const timestamp = getTimestamp();
47
- pushHistoryState({ timestamp, scrollPosition: null }, url);
52
+ pushHistoryState({ timestamp, scrollPosition: null, triggedBy: 'vike' }, url);
48
53
  }
49
54
  else {
50
55
  replaceHistoryState(getHistoryState(), url);
@@ -67,5 +72,22 @@ function replaceHistoryState(state, url) {
67
72
  window.history.replaceState(state, '', url ?? /* Passing `undefined` chokes older Edge versions */ null);
68
73
  }
69
74
  function pushHistoryState(state, url) {
70
- window.history.pushState(state, '', url);
75
+ pushStateOriginal(state, '', url);
76
+ }
77
+ function monkeyPatchHistoryPushState() {
78
+ globalObject.pushStateOriginal = globalObject.pushStateOriginal ?? window.history.pushState;
79
+ window.history.pushState = (stateFromUser = {}, ...rest) => {
80
+ assertUsage(null === stateFromUser || undefined === stateFromUser || isObject(stateFromUser), 'history.pushState(state) argument state must be an object');
81
+ const state = {
82
+ scrollPosition: getScrollPosition(),
83
+ timestamp: getTimestamp(),
84
+ ...stateFromUser,
85
+ // Don't allow user to overwrite triggedBy as it would break Vike's handling of the 'popstate' event
86
+ triggedBy: 'user'
87
+ };
88
+ return pushStateOriginal(state, ...rest);
89
+ };
90
+ }
91
+ function pushStateOriginal(...args) {
92
+ globalObject.pushStateOriginal.apply(history, args);
71
93
  }
@@ -0,0 +1,2 @@
1
+ export { installClientRouter };
2
+ declare function installClientRouter(): void;
@@ -0,0 +1,22 @@
1
+ export { installClientRouter };
2
+ import { assert } from './utils.js';
3
+ import { initHistoryState, monkeyPatchHistoryPushState } from './history.js';
4
+ import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
5
+ import { onBrowserHistoryNavigation } from './onBrowserHistoryNavigation.js';
6
+ import { onLinkClick } from './onLinkClick.js';
7
+ import { setupNativeScrollRestoration } from './scrollRestoration.js';
8
+ import { autoSaveScrollPosition } from './setScrollPosition.js';
9
+ function installClientRouter() {
10
+ setupNativeScrollRestoration();
11
+ initHistoryState();
12
+ autoSaveScrollPosition();
13
+ monkeyPatchHistoryPushState();
14
+ // First initial render
15
+ assert(getRenderCount() === 0);
16
+ renderPageClientSide({ scrollTarget: 'preserve-scroll', isBackwardNavigation: null, isClientSideNavigation: false });
17
+ assert(getRenderCount() === 1);
18
+ // Intercept <a> links
19
+ onLinkClick();
20
+ // Handle back-/forward navigation
21
+ onBrowserHistoryNavigation();
22
+ }
@@ -0,0 +1,8 @@
1
+ export { isClientSideRoutable };
2
+ import type { PageFile } from '../../shared/getPageFiles.js';
3
+ import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
4
+ type PageContextPageFiles = {
5
+ _pageFilesAll: PageFile[];
6
+ _pageConfigs: PageConfigRuntime[];
7
+ };
8
+ declare function isClientSideRoutable(pageId: string, pageContext: PageContextPageFiles): Promise<boolean>;
@@ -0,0 +1,12 @@
1
+ export { isClientSideRoutable };
2
+ import { analyzePageClientSideInit } from '../../shared/getPageFiles/analyzePageClientSide.js';
3
+ import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
4
+ import { analyzeClientSide } from '../../shared/getPageFiles/analyzeClientSide.js';
5
+ async function isClientSideRoutable(pageId, pageContext) {
6
+ await analyzePageClientSideInit(pageContext._pageFilesAll, pageId, {
7
+ sharedPageFilesAlreadyLoaded: false
8
+ });
9
+ const pageConfig = findPageConfig(pageContext._pageConfigs, pageId);
10
+ const { isClientSideRenderable, isClientRouting } = analyzeClientSide(pageConfig, pageContext._pageFilesAll, pageId);
11
+ return isClientSideRenderable && isClientRouting;
12
+ }
@@ -1,6 +1,5 @@
1
1
  export { navigate };
2
2
  export { reload };
3
- export { defineNavigate };
4
3
  /** Programmatically navigate to a new page.
5
4
  *
6
5
  * https://vike.dev/navigate
@@ -13,5 +12,4 @@ declare function navigate(url: string, { keepScrollPosition, overwriteLastHistor
13
12
  keepScrollPosition?: boolean | undefined;
14
13
  overwriteLastHistoryEntry?: boolean | undefined;
15
14
  }): Promise<void>;
16
- declare function defineNavigate(navigate_: typeof navigate): void;
17
15
  declare function reload(): Promise<void>;
@@ -1,9 +1,8 @@
1
1
  export { navigate };
2
2
  export { reload };
3
- export { defineNavigate };
4
- import { assertUsage, isBrowser, getGlobalObject, assertClientRouting, checkIfClientRouting, getCurrentUrl } from './utils.js';
3
+ import { renderPageClientSide } from './renderPageClientSide.js';
4
+ import { assertUsage, isBrowser, assertClientRouting, checkIfClientRouting, getCurrentUrl } from './utils.js';
5
5
  assertClientRouting();
6
- const globalObject = getGlobalObject('navigate.ts', {});
7
6
  /** Programmatically navigate to a new page.
8
7
  *
9
8
  * https://vike.dev/navigate
@@ -15,7 +14,6 @@ const globalObject = getGlobalObject('navigate.ts', {});
15
14
  async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryEntry = false } = {}) {
16
15
  assertUsage(isBrowser(), 'The navigate() function can be called only on the client-side', { showStackTrace: true });
17
16
  const errMsg = 'navigate() works only with Client Routing, see https://vike.dev/navigate';
18
- assertUsage(globalObject.navigate, errMsg, { showStackTrace: true });
19
17
  assertUsage(checkIfClientRouting(), errMsg, { showStackTrace: true });
20
18
  assertUsage(url, '[navigate(url)] Missing argument url', { showStackTrace: true });
21
19
  assertUsage(typeof url === 'string', '[navigate(url)] Argument url should be a string', { showStackTrace: true });
@@ -24,10 +22,13 @@ async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryE
24
22
  assertUsage(url.startsWith('/'), '[navigate(url)] Argument url should start with a leading /', {
25
23
  showStackTrace: true
26
24
  });
27
- await globalObject.navigate(url, { keepScrollPosition, overwriteLastHistoryEntry });
28
- }
29
- function defineNavigate(navigate_) {
30
- globalObject.navigate = navigate_;
25
+ const scrollTarget = keepScrollPosition ? 'preserve-scroll' : 'scroll-to-top-or-hash';
26
+ await renderPageClientSide({
27
+ scrollTarget,
28
+ urlOriginal: url,
29
+ overwriteLastHistoryEntry,
30
+ isBackwardNavigation: false
31
+ });
31
32
  }
32
33
  async function reload() {
33
34
  await navigate(getCurrentUrl());
@@ -0,0 +1,4 @@
1
+ export { onBrowserHistoryNavigation };
2
+ export { updateState };
3
+ declare function onBrowserHistoryNavigation(): void;
4
+ declare function updateState(): void;
@@ -0,0 +1,63 @@
1
+ export { onBrowserHistoryNavigation };
2
+ export { updateState };
3
+ import { getCurrentUrl, getGlobalObject } from './utils.js';
4
+ import { initHistoryState, getHistoryState } from './history.js';
5
+ import { renderPageClientSide } from './renderPageClientSide.js';
6
+ import { setScrollPosition } from './setScrollPosition.js';
7
+ const globalObject = getGlobalObject('onBrowserHistoryNavigation.ts', { previousState: getState() });
8
+ function onBrowserHistoryNavigation() {
9
+ // - The popstate event is trigged upon:
10
+ // - Back-/forward navigation.
11
+ // - By user clicking on his browser's back-/forward navigation (or using a shortcut)
12
+ // - By JavaScript: `history.back()` / `history.forward()`
13
+ // - URL hash change.
14
+ // - By user clicking on a hash link `<a href="#some-hash" />`
15
+ // - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
16
+ // - By JavaScript: `location.hash = 'some-hash'`
17
+ // - The `event` of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
18
+ window.addEventListener('popstate', () => {
19
+ const currentState = getState();
20
+ const scrollTarget = currentState.historyState.scrollPosition || 'scroll-to-top-or-hash';
21
+ const isUserLandPushStateNavigation = currentState.historyState.triggedBy === 'user';
22
+ const isHashNavigation = currentState.urlWithoutHash === globalObject.previousState.urlWithoutHash;
23
+ const isBackwardNavigation = !currentState.historyState.timestamp || !globalObject.previousState.historyState.timestamp
24
+ ? null
25
+ : currentState.historyState.timestamp < globalObject.previousState.historyState.timestamp;
26
+ globalObject.previousState = currentState;
27
+ if (isHashNavigation && !isUserLandPushStateNavigation) {
28
+ // - `history.state` is uninitialized (`null`) when:
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).
31
+ // - `history.state` is `null` when uninitialized: https://developer.mozilla.org/en-US/docs/Web/API/History/state
32
+ // - Alternatively, we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
33
+ // - Problem: we cannot intercept `window.location.hash = '#section'`. (Or maybe we can with the `hashchange` event?)
34
+ // - Other potential problem: would there be a conflict when the user wants to override the browser's default behavior? E.g. for smooth scrolling, or when using hashes for saving states of some fancy animations.
35
+ // - Another alternative: we use the browser's scroll restoration mechanism (see `browserNativeScrollRestoration_enable()` below).
36
+ // - Problem: not clear when to call `browserNativeScrollRestoration_disable()`/`browserNativeScrollRestoration_enable()`
37
+ // - Other potential problem are inconsistencies between browsers: specification says that setting `window.history.scrollRestoration` only affects the current entry in the session history. But this seems to contradict what folks saying.
38
+ // - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
39
+ // - https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
40
+ if (window.history.state === null) {
41
+ // The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `initHistoryState()`.
42
+ initHistoryState();
43
+ globalObject.previousState = getState();
44
+ }
45
+ else {
46
+ // If `history.state !== null` then it means that `popstate` was triggered by the user clicking on his browser's forward/backward history button.
47
+ setScrollPosition(scrollTarget);
48
+ }
49
+ }
50
+ else {
51
+ renderPageClientSide({ scrollTarget, isBackwardNavigation, isUserLandPushStateNavigation });
52
+ }
53
+ });
54
+ }
55
+ function getState() {
56
+ return {
57
+ urlWithoutHash: getCurrentUrl({ withoutHash: true }),
58
+ historyState: getHistoryState()
59
+ };
60
+ }
61
+ function updateState() {
62
+ globalObject.previousState = getState();
63
+ }
@@ -0,0 +1,2 @@
1
+ export { onLinkClick };
2
+ declare function onLinkClick(): void;
@@ -0,0 +1,40 @@
1
+ // Code adapted from https://github.com/HenrikJoreteg/internal-nav-helper/blob/5199ec5448d0b0db7ec63cf76d88fa6cad878b7d/src/index.js#L11-L29
2
+ export { onLinkClick };
3
+ import { assert } from './utils.js';
4
+ import { skipLink } from './skipLink.js';
5
+ import { renderPageClientSide } from './renderPageClientSide.js';
6
+ function onLinkClick() {
7
+ document.addEventListener('click', handler);
8
+ }
9
+ function handler(ev) {
10
+ if (!isNormalLeftClick(ev))
11
+ return;
12
+ const linkTag = findLinkTag(ev.target);
13
+ if (!linkTag)
14
+ return;
15
+ const url = linkTag.getAttribute('href');
16
+ if (skipLink(linkTag))
17
+ return;
18
+ assert(url);
19
+ ev.preventDefault();
20
+ const keepScrollPosition = ![null, 'false'].includes(linkTag.getAttribute('keep-scroll-position'));
21
+ const scrollTarget = keepScrollPosition ? 'preserve-scroll' : 'scroll-to-top-or-hash';
22
+ renderPageClientSide({
23
+ scrollTarget,
24
+ urlOriginal: url,
25
+ isBackwardNavigation: false
26
+ });
27
+ }
28
+ function isNormalLeftClick(ev) {
29
+ return ev.button === 0 && !ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey;
30
+ }
31
+ function findLinkTag(target) {
32
+ while (target.tagName !== 'A') {
33
+ const { parentNode } = target;
34
+ if (!parentNode) {
35
+ return null;
36
+ }
37
+ target = parentNode;
38
+ }
39
+ return target;
40
+ }