vike 0.4.235-commit-8f42b16 → 0.4.235-commit-9b9289b

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 (37) hide show
  1. package/dist/cjs/node/runtime/globalContext.js +18 -6
  2. package/dist/cjs/node/runtime/renderPage/createHttpResponse/getCacheControl.js +7 -7
  3. package/dist/cjs/node/runtime/renderPage/createHttpResponse.js +8 -5
  4. package/dist/cjs/node/runtime/renderPage/loadPageConfigsLazyServerSide.js +25 -0
  5. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -0
  6. package/dist/cjs/node/runtime/renderPage.js +1 -0
  7. package/dist/cjs/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +4 -0
  8. package/dist/cjs/node/vite/shared/resolveVikeConfigInternal/filesystemRouting.js +4 -6
  9. package/dist/cjs/shared/createGlobalContextShared.js +18 -7
  10. package/dist/cjs/shared/route/loadPageRoutes.js +7 -1
  11. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  12. package/dist/esm/client/runtime-client-routing/getPageContextFromHooks.d.ts +8 -0
  13. package/dist/esm/client/runtime-client-routing/renderPageClientSide.d.ts +2 -0
  14. package/dist/esm/client/shared/createGetGlobalContextClient.d.ts +2 -2
  15. package/dist/esm/node/prerender/runPrerender.d.ts +1 -0
  16. package/dist/esm/node/runtime/globalContext.d.ts +14 -12
  17. package/dist/esm/node/runtime/globalContext.js +20 -8
  18. package/dist/esm/node/runtime/renderPage/createHttpResponse/getCacheControl.d.ts +3 -3
  19. package/dist/esm/node/runtime/renderPage/createHttpResponse/getCacheControl.js +7 -7
  20. package/dist/esm/node/runtime/renderPage/createHttpResponse.d.ts +1 -0
  21. package/dist/esm/node/runtime/renderPage/createHttpResponse.js +8 -5
  22. package/dist/esm/node/runtime/renderPage/loadPageConfigsLazyServerSide.d.ts +5 -2
  23. package/dist/esm/node/runtime/renderPage/loadPageConfigsLazyServerSide.js +25 -0
  24. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +2 -0
  25. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -0
  26. package/dist/esm/node/runtime/renderPage.js +1 -0
  27. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +4 -0
  28. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/filesystemRouting.js +4 -6
  29. package/dist/esm/shared/createGlobalContextShared.d.ts +3 -3
  30. package/dist/esm/shared/createGlobalContextShared.js +18 -7
  31. package/dist/esm/shared/route/loadPageRoutes.d.ts +5 -0
  32. package/dist/esm/shared/route/loadPageRoutes.js +7 -1
  33. package/dist/esm/types/Config.d.ts +7 -0
  34. package/dist/esm/types/PageContext.d.ts +8 -2
  35. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  36. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  37. package/package.json +1 -1
@@ -42,7 +42,7 @@ const loggerRuntime_js_1 = require("./loggerRuntime.js");
42
42
  const getVikeConfigError_js_1 = require("../shared/getVikeConfigError.js");
43
43
  const isNewError_js_1 = require("./renderPage/isNewError.js");
44
44
  const debug = (0, utils_js_1.createDebugger)('vike:globalContext');
45
- const globalObject = (0, utils_js_1.getGlobalObject)('runtime/globalContext.ts', getInitialGlobalContext());
45
+ const globalObject = (0, utils_js_1.getGlobalObject)('runtime/globalContext.ts', getInitialGlobalObject());
46
46
  // Trick to break down TypeScript circular dependency
47
47
  // https://chat.deepseek.com/a/chat/s/d7e9f90a-c7f3-4108-9cd5-4ad6caed3539
48
48
  const globalObjectTyped = globalObject;
@@ -236,6 +236,7 @@ function assertViteManifest(manifest) {
236
236
  async function loadBuildEntry(outDir) {
237
237
  debug('loadBuildEntry()');
238
238
  if (globalObject.globalContext) {
239
+ debug('loadBuildEntry() - already done');
239
240
  return;
240
241
  }
241
242
  if (!globalObject.buildEntry) {
@@ -261,6 +262,8 @@ async function loadBuildEntry(outDir) {
261
262
  globalObject.buildInfo = buildEntry.buildInfo;
262
263
  await setGlobalContext(buildEntry.virtualFileExports);
263
264
  }
265
+ // This is the production entry, see:
266
+ // https://github.com/vikejs/vike/blob/798e5465dc3e3e6723b38b601a50350c0a006fb8/packages/vike/node/vite/plugins/pluginBuild/pluginBuildEntry.ts#L47
264
267
  async function setGlobalContext_buildEntry(buildEntry) {
265
268
  debug('setGlobalContext_buildEntry()');
266
269
  setIsProduction(true);
@@ -270,6 +273,7 @@ async function setGlobalContext_buildEntry(buildEntry) {
270
273
  (0, utils_js_1.assert)(globalObject.buildEntry); // ensure no infinite loop
271
274
  await loadBuildEntry();
272
275
  assertGlobalContextIsDefined();
276
+ debug('setGlobalContext_buildEntry() - done');
273
277
  }
274
278
  function assertBuildEntry(buildEntry) {
275
279
  (0, utils_js_1.assert)((0, utils_js_1.isObject)(buildEntry));
@@ -366,8 +370,9 @@ async function updateUserFiles() {
366
370
  return onSuccess();
367
371
  }
368
372
  async function setGlobalContext(virtualFileExports) {
373
+ debug('setGlobalContext()');
369
374
  (0, utils_js_1.assert)(!(0, getVikeConfigError_js_1.getVikeConfigErrorBuild)());
370
- const globalContext = await (0, createGlobalContextShared_js_1.createGlobalContextShared)(virtualFileExports, globalObject, addGlobalContext);
375
+ const globalContext = await (0, createGlobalContextShared_js_1.createGlobalContextShared)(virtualFileExports, globalObject, addGlobalContextAsync, addGlobalContextSync);
371
376
  (0, assertV1Design_js_1.assertV1Design)(
372
377
  // pageConfigs is PageConfigRuntime[] but assertV1Design() requires PageConfigBuildTime[]
373
378
  globalContext._pageConfigs.length > 0, globalContext._pageFilesAll);
@@ -376,8 +381,15 @@ async function setGlobalContext(virtualFileExports) {
376
381
  // Never actually used, only used for TypeScript `ReturnType<typeof setGlobalContext>`
377
382
  return globalContext;
378
383
  }
379
- async function addGlobalContext(globalContext) {
384
+ async function addGlobalContextAsync(globalContext) {
380
385
  const { pageRoutes, onBeforeRouteHook } = await (0, loadPageRoutes_js_1.loadPageRoutes)(globalContext._pageFilesAll, globalContext._pageConfigs, globalContext._pageConfigGlobal, globalContext._allPageIds);
386
+ return addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook);
387
+ }
388
+ function addGlobalContextSync(globalContext) {
389
+ const { pageRoutes, onBeforeRouteHook } = (0, loadPageRoutes_js_1.loadPageRoutesSync)(globalContext._pageFilesAll, globalContext._pageConfigs, globalContext._pageConfigGlobal, globalContext._allPageIds);
390
+ return addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook);
391
+ }
392
+ function addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook) {
381
393
  const globalContextBase = {
382
394
  isClientSide: false,
383
395
  _pageRoutes: pageRoutes,
@@ -436,10 +448,10 @@ async function addGlobalContext(globalContext) {
436
448
  }
437
449
  function clearGlobalContext() {
438
450
  debug('clearGlobalContext()');
439
- (0, utils_js_1.objectReplace)(globalObject, getInitialGlobalContext(), ['buildEntryPrevious']);
451
+ (0, utils_js_1.objectReplace)(globalObject, getInitialGlobalObject(), ['buildEntryPrevious']);
440
452
  }
441
- function getInitialGlobalContext() {
442
- debug('getInitialGlobalContext()');
453
+ function getInitialGlobalObject() {
454
+ debug('getInitialGlobalObject()');
443
455
  const { promise: viteDevServerPromise, resolve: viteDevServerPromiseResolve } = (0, utils_js_1.genPromise)();
444
456
  return {
445
457
  viteDevServerPromise,
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cacheControlDisable = void 0;
3
4
  exports.getCacheControl = getCacheControl;
4
5
  const helpers_js_1 = require("../../../../shared/page-configs/helpers.js");
5
6
  const getConfigValueRuntime_js_1 = require("../../../../shared/page-configs/getConfigValueRuntime.js");
6
- const defaultValue = 'no-store, max-age=0';
7
- function getCacheControl(pageId, pageConfigs, statusCode) {
8
- // TO-DO/next-major-release: remove
7
+ const cacheControlDisable = 'no-store, max-age=0';
8
+ exports.cacheControlDisable = cacheControlDisable;
9
+ function getCacheControl(pageId, pageConfigs) {
10
+ // TO-DO/next-major-release: remove this line
9
11
  if (pageConfigs.length === 0)
10
- return defaultValue;
11
- if (statusCode > 499)
12
- return defaultValue;
12
+ return cacheControlDisable;
13
13
  if (pageId) {
14
14
  const pageConfig = (0, helpers_js_1.getPageConfig)(pageId, pageConfigs);
15
15
  const configValue = (0, getConfigValueRuntime_js_1.getConfigValueRuntime)(pageConfig, 'cacheControl', 'string');
@@ -20,5 +20,5 @@ function getCacheControl(pageId, pageConfigs, statusCode) {
20
20
  // - Disabling caching by default is the safest strategy, because caching is problematic with authentication as described in https://github.com/vikejs/vike/issues/1275#issuecomment-1824366875
21
21
  // - Are there use cases when we don't need to disable caching?
22
22
  // - When there isn't any <script id="vike_pageContext" type="application/json"> then we can safely have caching. (We don't implement this exception because we're lazy and it's quite a rare situation.)
23
- return defaultValue;
23
+ return cacheControlDisable;
24
24
  }
@@ -11,8 +11,8 @@ const utils_js_1 = require("../utils.js");
11
11
  const error_page_js_1 = require("../../../shared/error-page.js");
12
12
  const getHttpResponseBody_js_1 = require("./getHttpResponseBody.js");
13
13
  const getEarlyHints_js_1 = require("./getEarlyHints.js");
14
- const getCacheControl_js_1 = require("./createHttpResponse/getCacheControl.js");
15
14
  const assertNoInfiniteHttpRedirect_js_1 = require("./createHttpResponse/assertNoInfiniteHttpRedirect.js");
15
+ const getCacheControl_js_1 = require("./createHttpResponse/getCacheControl.js");
16
16
  async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
17
17
  let statusCode = pageContext.abortStatusCode;
18
18
  if (!statusCode) {
@@ -31,10 +31,13 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
31
31
  }
32
32
  const earlyHints = (0, getEarlyHints_js_1.getEarlyHints)(await pageContext.__getPageAssets());
33
33
  const headers = [];
34
- const cacheControl = (0, getCacheControl_js_1.getCacheControl)(pageContext.pageId, pageContext._globalContext._pageConfigs, statusCode);
35
- if (cacheControl) {
36
- headers.push(['Cache-Control', cacheControl]);
37
- }
34
+ const headersResponse = pageContext.headersResponse || new Headers();
35
+ headersResponse.forEach((value, key) => {
36
+ headers.push([key, value]);
37
+ });
38
+ // An 5xx error page shouldn't be cached (it should be temporary)
39
+ if (statusCode >= 500)
40
+ headersResponse.set('Cache-Control', getCacheControl_js_1.cacheControlDisable);
38
41
  return createHttpResponse(statusCode, 'text/html;charset=utf-8', headers, htmlRender, earlyHints, renderHook);
39
42
  }
40
43
  function createHttpResponse404(errMsg404) {
@@ -11,12 +11,15 @@ const findPageConfig_js_1 = require("../../../shared/page-configs/findPageConfig
11
11
  const analyzePage_js_1 = require("./analyzePage.js");
12
12
  const loadConfigValues_js_1 = require("../../../shared/page-configs/loadConfigValues.js");
13
13
  const execHookServer_js_1 = require("./execHookServer.js");
14
+ const getCacheControl_js_1 = require("./createHttpResponse/getCacheControl.js");
15
+ // TODO/now: rename?
14
16
  async function loadPageConfigsLazyServerSideAndExecHook(pageContext) {
15
17
  const pageContextAddendum = await loadPageConfigsLazyServerSide(pageContext);
16
18
  (0, utils_js_1.objectAssign)(pageContext, pageContextAddendum);
17
19
  await (0, execHookServer_js_1.execHookServer)('onCreatePageContext', pageContext);
18
20
  return pageContext;
19
21
  }
22
+ // TODO/now: rename?
20
23
  async function loadPageConfigsLazyServerSide(pageContext) {
21
24
  const pageConfig = (0, findPageConfig_js_1.findPageConfig)(pageContext._globalContext._pageConfigs, pageContext.pageId); // Make pageConfig globally available as pageContext._pageConfig ?
22
25
  const globalContext = pageContext._globalContext;
@@ -50,6 +53,7 @@ async function loadPageConfigsLazyServerSide(pageContext) {
50
53
  _isHtmlOnly: isHtmlOnly,
51
54
  _passToClient: passToClient,
52
55
  _pageFilePathsLoaded: pageFilesLoaded.map((p) => p.filePath),
56
+ headersResponse: resolveHeadersResponse(pageContext, pageContextAddendum),
53
57
  });
54
58
  (0, utils_js_1.objectAssign)(pageContextAddendum, {
55
59
  __getPageAssets: async () => {
@@ -102,6 +106,7 @@ async function loadPageConfigsLazyServerSide(pageContext) {
102
106
  });
103
107
  return pageContextAddendum;
104
108
  }
109
+ // TODO/now: rename?
105
110
  async function loadPageUserFiles(pageFilesAll, pageConfig, pageConfigGlobal, pageId, isDev) {
106
111
  const pageFilesServerSide = (0, getPageFiles_js_1.getPageFilesServerSide)(pageFilesAll, pageId);
107
112
  const pageConfigLoaded = !pageConfig ? null : await (0, loadConfigValues_js_1.loadConfigValues)(pageConfig, isDev);
@@ -112,3 +117,23 @@ async function loadPageUserFiles(pageFilesAll, pageConfig, pageConfigGlobal, pag
112
117
  pageFilesLoaded: pageFilesServerSide,
113
118
  };
114
119
  }
120
+ function resolveHeadersResponse(
121
+ // TODO/now: merge pageContextAddendum with pageContext
122
+ pageContext, pageContextAddendum) {
123
+ const headersResponse = mergeHeaders(pageContextAddendum.config.headersResponse);
124
+ if (!headersResponse.get('Cache-Control')) {
125
+ const cacheControl = (0, getCacheControl_js_1.getCacheControl)(pageContext.pageId, pageContext._globalContext._pageConfigs);
126
+ if (cacheControl)
127
+ headersResponse.set('Cache-Control', cacheControl);
128
+ }
129
+ return headersResponse;
130
+ }
131
+ function mergeHeaders(headersList = []) {
132
+ const headersMerged = new Headers();
133
+ headersList.forEach((headers) => {
134
+ new Headers(headers).forEach((value, key) => {
135
+ headersMerged.append(key, value);
136
+ });
137
+ });
138
+ return headersMerged;
139
+ }
@@ -19,6 +19,7 @@ const preparePageContextForPublicUsageServer_js_1 = require("./preparePageContex
19
19
  const execHookGuard_js_1 = require("../../../shared/route/execHookGuard.js");
20
20
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
21
21
  const isServerSideError_js_1 = require("../../../shared/misc/isServerSideError.js");
22
+ // TODO/now: rename?
22
23
  async function renderPageAlreadyRouted(pageContext) {
23
24
  // pageContext.pageId can either be the:
24
25
  // - ID of the page matching the routing, or the
@@ -175,6 +175,7 @@ async function renderPageOnError(errNominalPage, pageContextBegin, pageContextNo
175
175
  return (0, handleErrorWithoutErrorPage_js_1.handleErrorWithoutErrorPage)(pageContextErrorPageInit);
176
176
  }
177
177
  else {
178
+ // TODO/now: minor refactor
178
179
  (0, utils_js_1.objectAssign)(pageContextErrorPageInit, { pageId: errorPageId });
179
180
  }
180
181
  }
@@ -212,6 +212,10 @@ const configDefinitionsBuiltIn = {
212
212
  env: { server: true },
213
213
  global: true,
214
214
  },
215
+ headersResponse: {
216
+ env: { server: true },
217
+ cumulative: true,
218
+ },
215
219
  };
216
220
  exports.configDefinitionsBuiltIn = configDefinitionsBuiltIn;
217
221
  function getConfigEnv(configValueSources, configName) {
@@ -36,12 +36,10 @@ function getFilesystemRouteString(locationId) {
36
36
  function getInheritanceRoot(locationId) {
37
37
  return getLogicalPath(locationId, [
38
38
  'renderer',
39
- // - Enable hooks defined by vike-{react,vue,solid} such as +onBeforeRenderClient to be defined at the root directory. In other words, avoid following error:
40
- // ```bash
41
- // [11:09:43.072][/test-preview.test.ts][npm run preview][stderr] Error: [vike][Wrong Usage] /+onBeforeRenderClient.ts sets the value of the config onBeforeRenderClient which is a custom config that is defined with https://vike.dev/meta at a path that doesn't apply to / — see https://vike.dev/config#inheritance
42
- // ```
43
- // - Not sure if it's a good idea? Could it make config inheritance confusing? Let's try for now and see how it goes.
44
- // - TO-DO/eventually: update docs https://github.com/vikejs/vike/blob/5fcdc4d5094f1a4dcbefc0b481cdd30a205aef2d/docs/pages/filesystem-routing/%2BPage.mdx?plain=1#L98
39
+ // Enable hooks defined by vike-{react,vue,solid} such as +onBeforeRenderClient to be defined at the root directory. In other words, avoid following error:
40
+ // ```bash
41
+ // [11:09:43.072][/test-preview.test.ts][npm run preview][stderr] Error: [vike][Wrong Usage] /+onBeforeRenderClient.ts sets the value of the config onBeforeRenderClient which is a custom config that is defined with https://vike.dev/meta at a path that doesn't apply to / — see https://vike.dev/config#inheritance
42
+ // ```
45
43
  'pages',
46
44
  ]);
47
45
  }
@@ -10,10 +10,24 @@ const prepareGlobalContextForPublicUsage_js_1 = require("./prepareGlobalContextF
10
10
  const getHook_js_1 = require("./hooks/getHook.js");
11
11
  const getGlobalContextSyncErrMsg = "The global context isn't set yet, call getGlobalContextSync() later or use getGlobalContext() instead.";
12
12
  exports.getGlobalContextSyncErrMsg = getGlobalContextSyncErrMsg;
13
- async function createGlobalContextShared(virtualFileExports, globalObject, addGlobalContext) {
13
+ async function createGlobalContextShared(virtualFileExports, globalObject, addGlobalContextAsync, addGlobalContextSync) {
14
14
  const globalContext = createGlobalContextBase(virtualFileExports);
15
- const globalContextAddendum = await addGlobalContext?.(globalContext);
16
- (0, utils_js_1.objectAssign)(globalContext, globalContextAddendum);
15
+ let isNewGlobalContext;
16
+ if (!globalObject.globalContext) {
17
+ globalObject.globalContext = globalContext;
18
+ isNewGlobalContext = false;
19
+ }
20
+ else {
21
+ isNewGlobalContext = true;
22
+ }
23
+ if (addGlobalContextSync && globalContext._pageConfigs.length > 0) {
24
+ const globalContextAddendum = addGlobalContextSync?.(globalContext);
25
+ (0, utils_js_1.objectAssign)(globalContext, globalContextAddendum);
26
+ }
27
+ else {
28
+ const globalContextAddendum = await addGlobalContextAsync?.(globalContext);
29
+ (0, utils_js_1.objectAssign)(globalContext, globalContextAddendum);
30
+ }
17
31
  const onCreateGlobalContextHooks = (0, getHook_js_1.getHookFromPageConfigGlobalCumulative)(globalContext._pageConfigGlobal, 'onCreateGlobalContext');
18
32
  let hooksCalled = false;
19
33
  if (!hooksAreEqual(globalObject.onCreateGlobalContextHooks ?? [], onCreateGlobalContextHooks)) {
@@ -21,10 +35,7 @@ async function createGlobalContextShared(virtualFileExports, globalObject, addGl
21
35
  await (0, execHook_js_1.execHookGlobal)('onCreateGlobalContext', globalContext._pageConfigGlobal, null, globalContext, prepareGlobalContextForPublicUsage_js_1.prepareGlobalContextForPublicUsage);
22
36
  hooksCalled = true;
23
37
  }
24
- if (!globalObject.globalContext) {
25
- globalObject.globalContext = globalContext;
26
- }
27
- else {
38
+ if (isNewGlobalContext) {
28
39
  // Singleton: ensure all `globalContext` user-land references are preserved & updated.
29
40
  if (hooksCalled) {
30
41
  (0, utils_js_1.objectReplace)(globalObject.globalContext, globalContext);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadPageRoutes = loadPageRoutes;
4
+ exports.loadPageRoutesSync = loadPageRoutesSync;
4
5
  const error_page_js_1 = require("../error-page.js");
5
6
  const utils_js_1 = require("./utils.js");
6
7
  const deduceRouteStringFromFilesystemPath_js_1 = require("./deduceRouteStringFromFilesystemPath.js");
@@ -12,8 +13,13 @@ const getHook_js_1 = require("../hooks/getHook.js");
12
13
  async function loadPageRoutes(
13
14
  // Remove all arguments and use GlobalContextServerInternal instead?
14
15
  pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds) {
15
- // TO-DO/next-major-release: remove & make this function sync
16
+ // TO-DO/next-major-release: remove this line, remove this function, rename loadPageRoutesSync() to loadPageRoutes()
16
17
  await Promise.all(pageFilesAll.filter((p) => p.fileType === '.page.route').map((p) => p.loadFile?.()));
18
+ return loadPageRoutesSync(pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds);
19
+ }
20
+ function loadPageRoutesSync(
21
+ // Remove all arguments and use GlobalContextServerInternal instead?
22
+ pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds) {
17
23
  const { onBeforeRouteHook, filesystemRoots } = getGlobalHooks(pageFilesAll, pageConfigs, pageConfigGlobal);
18
24
  const pageRoutes = getPageRoutes(filesystemRoots, pageFilesAll, pageConfigs, allPageIds);
19
25
  return { pageRoutes, onBeforeRouteHook };
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = void 0;
4
4
  // Automatically updated by @brillout/release-me
5
- exports.PROJECT_VERSION = '0.4.235-commit-8f42b16';
5
+ exports.PROJECT_VERSION = '0.4.235-commit-9b9289b';
@@ -85,6 +85,7 @@ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSer
85
85
  urlOriginal: string;
86
86
  headers: Record<string, string> | null;
87
87
  headersOriginal?: unknown;
88
+ headersResponse: Headers;
88
89
  is404: boolean | null;
89
90
  isClientSideNavigation: boolean;
90
91
  abortReason?: unknown;
@@ -109,6 +110,7 @@ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSer
109
110
  urlOriginal: string;
110
111
  headers: Record<string, string> | null;
111
112
  headersOriginal?: unknown;
113
+ headersResponse: Headers;
112
114
  is404: boolean | null;
113
115
  isClientSideNavigation: boolean;
114
116
  abortReason?: unknown;
@@ -156,6 +158,7 @@ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSer
156
158
  urlOriginal: string;
157
159
  headers: Record<string, string> | null;
158
160
  headersOriginal?: unknown;
161
+ headersResponse: Headers;
159
162
  is404: boolean | null;
160
163
  isClientSideNavigation: boolean;
161
164
  abortReason?: unknown;
@@ -180,6 +183,7 @@ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSer
180
183
  urlOriginal: string;
181
184
  headers: Record<string, string> | null;
182
185
  headersOriginal?: unknown;
186
+ headersResponse: Headers;
183
187
  is404: boolean | null;
184
188
  isClientSideNavigation: boolean;
185
189
  abortReason?: unknown;
@@ -295,6 +299,7 @@ declare function getPageContextFromClientHooks(pageContext: {
295
299
  urlOriginal: string;
296
300
  headers: Record<string, string> | null;
297
301
  headersOriginal?: unknown;
302
+ headersResponse: Headers;
298
303
  is404: boolean | null;
299
304
  isClientSideNavigation: boolean;
300
305
  abortReason?: unknown;
@@ -319,6 +324,7 @@ declare function getPageContextFromClientHooks(pageContext: {
319
324
  urlOriginal: string;
320
325
  headers: Record<string, string> | null;
321
326
  headersOriginal?: unknown;
327
+ headersResponse: Headers;
322
328
  is404: boolean | null;
323
329
  isClientSideNavigation: boolean;
324
330
  abortReason?: unknown;
@@ -364,6 +370,7 @@ declare function getPageContextFromClientHooks(pageContext: {
364
370
  urlOriginal: string;
365
371
  headers: Record<string, string> | null;
366
372
  headersOriginal?: unknown;
373
+ headersResponse: Headers;
367
374
  is404: boolean | null;
368
375
  isClientSideNavigation: boolean;
369
376
  abortReason?: unknown;
@@ -388,6 +395,7 @@ declare function getPageContextFromClientHooks(pageContext: {
388
395
  urlOriginal: string;
389
396
  headers: Record<string, string> | null;
390
397
  headersOriginal?: unknown;
398
+ headersResponse: Headers;
391
399
  is404: boolean | null;
392
400
  isClientSideNavigation: boolean;
393
401
  abortReason?: unknown;
@@ -95,6 +95,7 @@ declare function getPageContextBegin(isForErrorPage: boolean, { urlOriginal, isB
95
95
  urlOriginal: string;
96
96
  headers: Record<string, string> | null;
97
97
  headersOriginal?: unknown;
98
+ headersResponse: Headers;
98
99
  is404: boolean | null;
99
100
  isClientSideNavigation: boolean;
100
101
  abortReason?: unknown;
@@ -119,6 +120,7 @@ declare function getPageContextBegin(isForErrorPage: boolean, { urlOriginal, isB
119
120
  urlOriginal: string;
120
121
  headers: Record<string, string> | null;
121
122
  headersOriginal?: unknown;
123
+ headersResponse: Headers;
122
124
  is404: boolean | null;
123
125
  isClientSideNavigation: boolean;
124
126
  abortReason?: unknown;
@@ -23,14 +23,14 @@ declare function createGetGlobalContextClient<GlobalContextAddendum extends obje
23
23
  pages: {
24
24
  [k: string]: import("../../shared/page-configs/resolveVikeConfigPublic.js").VikeConfigPublicPageEager;
25
25
  };
26
- } & Awaited<{
26
+ } & {
27
27
  /**
28
28
  * Whether the environment is client-side or server-side / pre-rendering.
29
29
  *
30
30
  * We recommend using `import.meta.env.SSR` instead, see https://vike.dev/globalContext
31
31
  */
32
32
  isClientSide: true;
33
- } & Awaited<GlobalContextAddendum>>>;
33
+ } & Awaited<GlobalContextAddendum>>;
34
34
  type NeverExported = never;
35
35
  declare function getGlobalContext(): Promise<NeverExported>;
36
36
  declare function getGlobalContextSync(): NeverExported;
@@ -561,6 +561,7 @@ declare function createPageContextPrerendering(urlOriginal: string, prerenderCon
561
561
  _isHtmlOnly: boolean;
562
562
  _passToClient: string[];
563
563
  _pageFilePathsLoaded: string[];
564
+ headersResponse: Headers;
564
565
  } & {
565
566
  __getPageAssets: () => Promise<import("../runtime/renderPage/getPageAssets.js").PageAsset[]>;
566
567
  })) & {
@@ -21,8 +21,10 @@ export type { GlobalContextServerInternal as GlobalContextServerInternal };
21
21
  export type { GlobalContextServer };
22
22
  import type { ViteManifest } from '../../types/ViteManifest.js';
23
23
  import type { ResolvedConfig, ViteDevServer } from 'vite';
24
+ import { type PageRoutes } from '../../shared/route/loadPageRoutes.js';
24
25
  import type { ViteConfigRuntime } from '../vite/shared/getViteConfigRuntime.js';
25
26
  import type { GlobalContext } from '../../types/PageContext.js';
27
+ import type { Hook } from '../../shared/hooks/getHook.js';
26
28
  declare const vikeConfigErrorRecoverMsg: "Vike config loaded";
27
29
  type GlobalContextServer = Pick<GlobalContextServerInternal, 'assetsManifest' | 'config' | 'viteConfig' | 'viteConfigRuntime' | 'pages' | 'baseServer' | 'baseAssets' | 'isClientSide'> & Vike.GlobalContext & Vike.GlobalContextServer;
28
30
  type GlobalContextServerInternal = Awaited<ReturnType<typeof setGlobalContext>>;
@@ -64,8 +66,8 @@ declare function getGlobalContextServerInternal(): Promise<{
64
66
  baseServer: string;
65
67
  baseAssets: string;
66
68
  isClientSide: false;
67
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
68
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
69
+ _pageRoutes: PageRoutes;
70
+ _onBeforeRouteHook: Hook | null;
69
71
  }) | (Record<string, unknown> & {
70
72
  isGlobalContext: true;
71
73
  _isOriginalObject: true;
@@ -104,8 +106,8 @@ declare function getGlobalContextServerInternal(): Promise<{
104
106
  baseServer: string;
105
107
  baseAssets: string;
106
108
  isClientSide: false;
107
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
108
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
109
+ _pageRoutes: PageRoutes;
110
+ _onBeforeRouteHook: Hook | null;
109
111
  }) | (Record<string, unknown> & {
110
112
  isGlobalContext: true;
111
113
  _isOriginalObject: true;
@@ -144,8 +146,8 @@ declare function getGlobalContextServerInternal(): Promise<{
144
146
  baseServer: string;
145
147
  baseAssets: string;
146
148
  isClientSide: false;
147
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
148
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
149
+ _pageRoutes: PageRoutes;
150
+ _onBeforeRouteHook: Hook | null;
149
151
  });
150
152
  }>;
151
153
  /**
@@ -222,8 +224,8 @@ declare function setGlobalContext(virtualFileExports: unknown): Promise<{
222
224
  baseServer: string;
223
225
  baseAssets: string;
224
226
  isClientSide: false;
225
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
226
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
227
+ _pageRoutes: PageRoutes;
228
+ _onBeforeRouteHook: Hook | null;
227
229
  } | {
228
230
  _isPrerendering: true;
229
231
  viteConfig: ResolvedConfig;
@@ -244,8 +246,8 @@ declare function setGlobalContext(virtualFileExports: unknown): Promise<{
244
246
  baseServer: string;
245
247
  baseAssets: string;
246
248
  isClientSide: false;
247
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
248
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
249
+ _pageRoutes: PageRoutes;
250
+ _onBeforeRouteHook: Hook | null;
249
251
  } | {
250
252
  _isPrerendering: false;
251
253
  viteConfig: null;
@@ -266,7 +268,7 @@ declare function setGlobalContext(virtualFileExports: unknown): Promise<{
266
268
  baseServer: string;
267
269
  baseAssets: string;
268
270
  isClientSide: false;
269
- _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
270
- _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
271
+ _pageRoutes: PageRoutes;
272
+ _onBeforeRouteHook: Hook | null;
271
273
  })>;
272
274
  declare function clearGlobalContext(): void;
@@ -13,7 +13,7 @@ export { setGlobalContext_viteDevServer };
13
13
  export { setGlobalContext_viteConfig };
14
14
  export { setGlobalContext_isPrerendering };
15
15
  export { setGlobalContext_isProduction };
16
- export { setGlobalContext_buildEntry };
16
+ export { setGlobalContext_buildEntry }; // production entry
17
17
  export { clearGlobalContext };
18
18
  export { assertBuildInfo };
19
19
  export { updateUserFiles };
@@ -30,7 +30,7 @@ import { assert, onSetupRuntime, assertUsage, assertWarning, isPlainObject, obje
30
30
  import { importServerProductionEntry } from '@brillout/vite-plugin-server-entry/runtime';
31
31
  import { virtualFileIdEntryServer } from '../shared/virtualFiles/virtualFileEntry.js';
32
32
  import pc from '@brillout/picocolors';
33
- import { loadPageRoutes } from '../../shared/route/loadPageRoutes.js';
33
+ import { loadPageRoutes, loadPageRoutesSync } from '../../shared/route/loadPageRoutes.js';
34
34
  import { assertV1Design } from '../shared/assertV1Design.js';
35
35
  import { resolveBase } from '../shared/resolveBase.js';
36
36
  import { createGlobalContextShared, getGlobalContextSyncErrMsg, } from '../../shared/createGlobalContextShared.js';
@@ -39,7 +39,7 @@ import { logRuntimeError, logRuntimeInfo } from './loggerRuntime.js';
39
39
  import { getVikeConfigErrorBuild, setVikeConfigError } from '../shared/getVikeConfigError.js';
40
40
  import { hasAlreadyLogged } from './renderPage/isNewError.js';
41
41
  const debug = createDebugger('vike:globalContext');
42
- const globalObject = getGlobalObject('runtime/globalContext.ts', getInitialGlobalContext());
42
+ const globalObject = getGlobalObject('runtime/globalContext.ts', getInitialGlobalObject());
43
43
  // Trick to break down TypeScript circular dependency
44
44
  // https://chat.deepseek.com/a/chat/s/d7e9f90a-c7f3-4108-9cd5-4ad6caed3539
45
45
  const globalObjectTyped = globalObject;
@@ -232,6 +232,7 @@ function assertViteManifest(manifest) {
232
232
  async function loadBuildEntry(outDir) {
233
233
  debug('loadBuildEntry()');
234
234
  if (globalObject.globalContext) {
235
+ debug('loadBuildEntry() - already done');
235
236
  return;
236
237
  }
237
238
  if (!globalObject.buildEntry) {
@@ -257,6 +258,8 @@ async function loadBuildEntry(outDir) {
257
258
  globalObject.buildInfo = buildEntry.buildInfo;
258
259
  await setGlobalContext(buildEntry.virtualFileExports);
259
260
  }
261
+ // This is the production entry, see:
262
+ // https://github.com/vikejs/vike/blob/798e5465dc3e3e6723b38b601a50350c0a006fb8/packages/vike/node/vite/plugins/pluginBuild/pluginBuildEntry.ts#L47
260
263
  async function setGlobalContext_buildEntry(buildEntry) {
261
264
  debug('setGlobalContext_buildEntry()');
262
265
  setIsProduction(true);
@@ -266,6 +269,7 @@ async function setGlobalContext_buildEntry(buildEntry) {
266
269
  assert(globalObject.buildEntry); // ensure no infinite loop
267
270
  await loadBuildEntry();
268
271
  assertGlobalContextIsDefined();
272
+ debug('setGlobalContext_buildEntry() - done');
269
273
  }
270
274
  function assertBuildEntry(buildEntry) {
271
275
  assert(isObject(buildEntry));
@@ -362,8 +366,9 @@ async function updateUserFiles() {
362
366
  return onSuccess();
363
367
  }
364
368
  async function setGlobalContext(virtualFileExports) {
369
+ debug('setGlobalContext()');
365
370
  assert(!getVikeConfigErrorBuild());
366
- const globalContext = await createGlobalContextShared(virtualFileExports, globalObject, addGlobalContext);
371
+ const globalContext = await createGlobalContextShared(virtualFileExports, globalObject, addGlobalContextAsync, addGlobalContextSync);
367
372
  assertV1Design(
368
373
  // pageConfigs is PageConfigRuntime[] but assertV1Design() requires PageConfigBuildTime[]
369
374
  globalContext._pageConfigs.length > 0, globalContext._pageFilesAll);
@@ -372,8 +377,15 @@ async function setGlobalContext(virtualFileExports) {
372
377
  // Never actually used, only used for TypeScript `ReturnType<typeof setGlobalContext>`
373
378
  return globalContext;
374
379
  }
375
- async function addGlobalContext(globalContext) {
380
+ async function addGlobalContextAsync(globalContext) {
376
381
  const { pageRoutes, onBeforeRouteHook } = await loadPageRoutes(globalContext._pageFilesAll, globalContext._pageConfigs, globalContext._pageConfigGlobal, globalContext._allPageIds);
382
+ return addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook);
383
+ }
384
+ function addGlobalContextSync(globalContext) {
385
+ const { pageRoutes, onBeforeRouteHook } = loadPageRoutesSync(globalContext._pageFilesAll, globalContext._pageConfigs, globalContext._pageConfigGlobal, globalContext._allPageIds);
386
+ return addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook);
387
+ }
388
+ function addGlobalContextCommon(globalContext, pageRoutes, onBeforeRouteHook) {
377
389
  const globalContextBase = {
378
390
  isClientSide: false,
379
391
  _pageRoutes: pageRoutes,
@@ -432,10 +444,10 @@ async function addGlobalContext(globalContext) {
432
444
  }
433
445
  function clearGlobalContext() {
434
446
  debug('clearGlobalContext()');
435
- objectReplace(globalObject, getInitialGlobalContext(), ['buildEntryPrevious']);
447
+ objectReplace(globalObject, getInitialGlobalObject(), ['buildEntryPrevious']);
436
448
  }
437
- function getInitialGlobalContext() {
438
- debug('getInitialGlobalContext()');
449
+ function getInitialGlobalObject() {
450
+ debug('getInitialGlobalObject()');
439
451
  const { promise: viteDevServerPromise, resolve: viteDevServerPromiseResolve } = genPromise();
440
452
  return {
441
453
  viteDevServerPromise,
@@ -1,5 +1,5 @@
1
1
  export { getCacheControl };
2
+ export { cacheControlDisable };
2
3
  import type { PageConfigRuntime } from '../../../../types/PageConfig.js';
3
- import type { HttpResponse } from '../createHttpResponse.js';
4
- type StatusCode = HttpResponse['statusCode'];
5
- declare function getCacheControl(pageId: string | null, pageConfigs: PageConfigRuntime[], statusCode: StatusCode): string;
4
+ declare const cacheControlDisable = "no-store, max-age=0";
5
+ declare function getCacheControl(pageId: string | null, pageConfigs: PageConfigRuntime[]): string;
@@ -1,13 +1,13 @@
1
+ // TODO/now: move
1
2
  export { getCacheControl };
3
+ export { cacheControlDisable };
2
4
  import { getPageConfig } from '../../../../shared/page-configs/helpers.js';
3
5
  import { getConfigValueRuntime } from '../../../../shared/page-configs/getConfigValueRuntime.js';
4
- const defaultValue = 'no-store, max-age=0';
5
- function getCacheControl(pageId, pageConfigs, statusCode) {
6
- // TO-DO/next-major-release: remove
6
+ const cacheControlDisable = 'no-store, max-age=0';
7
+ function getCacheControl(pageId, pageConfigs) {
8
+ // TO-DO/next-major-release: remove this line
7
9
  if (pageConfigs.length === 0)
8
- return defaultValue;
9
- if (statusCode > 499)
10
- return defaultValue;
10
+ return cacheControlDisable;
11
11
  if (pageId) {
12
12
  const pageConfig = getPageConfig(pageId, pageConfigs);
13
13
  const configValue = getConfigValueRuntime(pageConfig, 'cacheControl', 'string');
@@ -18,5 +18,5 @@ function getCacheControl(pageId, pageConfigs, statusCode) {
18
18
  // - Disabling caching by default is the safest strategy, because caching is problematic with authentication as described in https://github.com/vikejs/vike/issues/1275#issuecomment-1824366875
19
19
  // - Are there use cases when we don't need to disable caching?
20
20
  // - When there isn't any <script id="vike_pageContext" type="application/json"> then we can safely have caching. (We don't implement this exception because we're lazy and it's quite a rare situation.)
21
- return defaultValue;
21
+ return cacheControlDisable;
22
22
  }
@@ -28,6 +28,7 @@ declare function createHttpResponsePage(htmlRender: HtmlRender, renderHook: null
28
28
  __getPageAssets: GetPageAssets;
29
29
  _globalContext: GlobalContextServerInternal;
30
30
  abortStatusCode?: AbortStatusCode;
31
+ headersResponse?: Headers;
31
32
  }): Promise<HttpResponse>;
32
33
  declare function createHttpResponse404(errMsg404: string): HttpResponse;
33
34
  declare function createHttpResponseBaseIsMissing(urlOriginal: string, baseServer: string): HttpResponse;
@@ -9,8 +9,8 @@ import { assert, assertWarning, escapeHtml } from '../utils.js';
9
9
  import { getErrorPageId, isErrorPage } from '../../../shared/error-page.js';
10
10
  import { getHttpResponseBody, getHttpResponseBodyStreamHandlers } from './getHttpResponseBody.js';
11
11
  import { getEarlyHints } from './getEarlyHints.js';
12
- import { getCacheControl } from './createHttpResponse/getCacheControl.js';
13
12
  import { assertNoInfiniteHttpRedirect } from './createHttpResponse/assertNoInfiniteHttpRedirect.js';
13
+ import { cacheControlDisable } from './createHttpResponse/getCacheControl.js';
14
14
  async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
15
15
  let statusCode = pageContext.abortStatusCode;
16
16
  if (!statusCode) {
@@ -29,10 +29,13 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
29
29
  }
30
30
  const earlyHints = getEarlyHints(await pageContext.__getPageAssets());
31
31
  const headers = [];
32
- const cacheControl = getCacheControl(pageContext.pageId, pageContext._globalContext._pageConfigs, statusCode);
33
- if (cacheControl) {
34
- headers.push(['Cache-Control', cacheControl]);
35
- }
32
+ const headersResponse = pageContext.headersResponse || new Headers();
33
+ headersResponse.forEach((value, key) => {
34
+ headers.push([key, value]);
35
+ });
36
+ // An 5xx error page shouldn't be cached (it should be temporary)
37
+ if (statusCode >= 500)
38
+ headersResponse.set('Cache-Control', cacheControlDisable);
36
39
  return createHttpResponse(statusCode, 'text/html;charset=utf-8', headers, htmlRender, earlyHints, renderHook);
37
40
  }
38
41
  function createHttpResponse404(errMsg404) {
@@ -1,6 +1,7 @@
1
1
  export { loadPageConfigsLazyServerSideAndExecHook };
2
2
  export type { PageContext_loadPageConfigsLazyServerSide };
3
3
  export type { PageConfigsLazy };
4
+ import { type VikeConfigPublicPageLazy } from '../../../shared/getPageFiles.js';
4
5
  import { PromiseType } from '../utils.js';
5
6
  import { PageContextGetPageAssets, type PageAsset } from './getPageAssets.js';
6
7
  import { type PageContextDebugRouteMatches } from './debugPageFiles.js';
@@ -13,19 +14,21 @@ type PageContext_loadPageConfigsLazyServerSide = PageContextGetPageAssets & Page
13
14
  _globalContext: GlobalContextServerInternal;
14
15
  };
15
16
  type PageConfigsLazy = PromiseType<ReturnType<typeof loadPageConfigsLazyServerSide>>;
16
- declare function loadPageConfigsLazyServerSideAndExecHook<PageContext extends PageContext_loadPageConfigsLazyServerSide & PageContextExecuteHook>(pageContext: PageContext): Promise<PageContext & import("../../../shared/getPageFiles.js").VikeConfigPublicPageLazy & {
17
+ declare function loadPageConfigsLazyServerSideAndExecHook<PageContext extends PageContext_loadPageConfigsLazyServerSide & PageContextExecuteHook>(pageContext: PageContext): Promise<PageContext & VikeConfigPublicPageLazy & {
17
18
  Page: unknown;
18
19
  _isHtmlOnly: boolean;
19
20
  _passToClient: string[];
20
21
  _pageFilePathsLoaded: string[];
22
+ headersResponse: Headers;
21
23
  } & {
22
24
  __getPageAssets: () => Promise<PageAsset[]>;
23
25
  }>;
24
- declare function loadPageConfigsLazyServerSide(pageContext: PageContext_loadPageConfigsLazyServerSide): Promise<import("../../../shared/getPageFiles.js").VikeConfigPublicPageLazy & {
26
+ declare function loadPageConfigsLazyServerSide(pageContext: PageContext_loadPageConfigsLazyServerSide): Promise<VikeConfigPublicPageLazy & {
25
27
  Page: unknown;
26
28
  _isHtmlOnly: boolean;
27
29
  _passToClient: string[];
28
30
  _pageFilePathsLoaded: string[];
31
+ headersResponse: Headers;
29
32
  } & {
30
33
  __getPageAssets: () => Promise<PageAsset[]>;
31
34
  }>;
@@ -9,12 +9,15 @@ import { findPageConfig } from '../../../shared/page-configs/findPageConfig.js';
9
9
  import { analyzePage } from './analyzePage.js';
10
10
  import { loadConfigValues } from '../../../shared/page-configs/loadConfigValues.js';
11
11
  import { execHookServer } from './execHookServer.js';
12
+ import { getCacheControl } from './createHttpResponse/getCacheControl.js';
13
+ // TODO/now: rename?
12
14
  async function loadPageConfigsLazyServerSideAndExecHook(pageContext) {
13
15
  const pageContextAddendum = await loadPageConfigsLazyServerSide(pageContext);
14
16
  objectAssign(pageContext, pageContextAddendum);
15
17
  await execHookServer('onCreatePageContext', pageContext);
16
18
  return pageContext;
17
19
  }
20
+ // TODO/now: rename?
18
21
  async function loadPageConfigsLazyServerSide(pageContext) {
19
22
  const pageConfig = findPageConfig(pageContext._globalContext._pageConfigs, pageContext.pageId); // Make pageConfig globally available as pageContext._pageConfig ?
20
23
  const globalContext = pageContext._globalContext;
@@ -48,6 +51,7 @@ async function loadPageConfigsLazyServerSide(pageContext) {
48
51
  _isHtmlOnly: isHtmlOnly,
49
52
  _passToClient: passToClient,
50
53
  _pageFilePathsLoaded: pageFilesLoaded.map((p) => p.filePath),
54
+ headersResponse: resolveHeadersResponse(pageContext, pageContextAddendum),
51
55
  });
52
56
  objectAssign(pageContextAddendum, {
53
57
  __getPageAssets: async () => {
@@ -100,6 +104,7 @@ async function loadPageConfigsLazyServerSide(pageContext) {
100
104
  });
101
105
  return pageContextAddendum;
102
106
  }
107
+ // TODO/now: rename?
103
108
  async function loadPageUserFiles(pageFilesAll, pageConfig, pageConfigGlobal, pageId, isDev) {
104
109
  const pageFilesServerSide = getPageFilesServerSide(pageFilesAll, pageId);
105
110
  const pageConfigLoaded = !pageConfig ? null : await loadConfigValues(pageConfig, isDev);
@@ -110,3 +115,23 @@ async function loadPageUserFiles(pageFilesAll, pageConfig, pageConfigGlobal, pag
110
115
  pageFilesLoaded: pageFilesServerSide,
111
116
  };
112
117
  }
118
+ function resolveHeadersResponse(
119
+ // TODO/now: merge pageContextAddendum with pageContext
120
+ pageContext, pageContextAddendum) {
121
+ const headersResponse = mergeHeaders(pageContextAddendum.config.headersResponse);
122
+ if (!headersResponse.get('Cache-Control')) {
123
+ const cacheControl = getCacheControl(pageContext.pageId, pageContext._globalContext._pageConfigs);
124
+ if (cacheControl)
125
+ headersResponse.set('Cache-Control', cacheControl);
126
+ }
127
+ return headersResponse;
128
+ }
129
+ function mergeHeaders(headersList = []) {
130
+ const headersMerged = new Headers();
131
+ headersList.forEach((headers) => {
132
+ new Headers(headers).forEach((value, key) => {
133
+ headersMerged.append(key, value);
134
+ });
135
+ });
136
+ return headersMerged;
137
+ }
@@ -145,6 +145,7 @@ declare function prerenderPage(pageContext: PageContextCreated & PageConfigsLazy
145
145
  _isHtmlOnly: boolean;
146
146
  _passToClient: string[];
147
147
  _pageFilePathsLoaded: string[];
148
+ headersResponse: Headers;
148
149
  } & {
149
150
  __getPageAssets: () => Promise<import("./getPageAssets.js").PageAsset[]>;
150
151
  } & {
@@ -279,6 +280,7 @@ declare function prerenderPage(pageContext: PageContextCreated & PageConfigsLazy
279
280
  _isHtmlOnly: boolean;
280
281
  _passToClient: string[];
281
282
  _pageFilePathsLoaded: string[];
283
+ headersResponse: Headers;
282
284
  } & {
283
285
  __getPageAssets: () => Promise<import("./getPageAssets.js").PageAsset[]>;
284
286
  } & {
@@ -14,6 +14,7 @@ import { preparePageContextForPublicUsageServer } from './preparePageContextForP
14
14
  import { execHookGuard } from '../../../shared/route/execHookGuard.js';
15
15
  import pc from '@brillout/picocolors';
16
16
  import { isServerSideError } from '../../../shared/misc/isServerSideError.js';
17
+ // TODO/now: rename?
17
18
  async function renderPageAlreadyRouted(pageContext) {
18
19
  // pageContext.pageId can either be the:
19
20
  // - ID of the page matching the routing, or the
@@ -170,6 +170,7 @@ async function renderPageOnError(errNominalPage, pageContextBegin, pageContextNo
170
170
  return handleErrorWithoutErrorPage(pageContextErrorPageInit);
171
171
  }
172
172
  else {
173
+ // TODO/now: minor refactor
173
174
  objectAssign(pageContextErrorPageInit, { pageId: errorPageId });
174
175
  }
175
176
  }
@@ -210,6 +210,10 @@ const configDefinitionsBuiltIn = {
210
210
  env: { server: true },
211
211
  global: true,
212
212
  },
213
+ headersResponse: {
214
+ env: { server: true },
215
+ cumulative: true,
216
+ },
213
217
  };
214
218
  function getConfigEnv(configValueSources, configName) {
215
219
  const configValueSource = getConfigValueSource(configValueSources, configName);
@@ -32,12 +32,10 @@ function getFilesystemRouteString(locationId) {
32
32
  function getInheritanceRoot(locationId) {
33
33
  return getLogicalPath(locationId, [
34
34
  'renderer',
35
- // - Enable hooks defined by vike-{react,vue,solid} such as +onBeforeRenderClient to be defined at the root directory. In other words, avoid following error:
36
- // ```bash
37
- // [11:09:43.072][/test-preview.test.ts][npm run preview][stderr] Error: [vike][Wrong Usage] /+onBeforeRenderClient.ts sets the value of the config onBeforeRenderClient which is a custom config that is defined with https://vike.dev/meta at a path that doesn't apply to / — see https://vike.dev/config#inheritance
38
- // ```
39
- // - Not sure if it's a good idea? Could it make config inheritance confusing? Let's try for now and see how it goes.
40
- // - TO-DO/eventually: update docs https://github.com/vikejs/vike/blob/5fcdc4d5094f1a4dcbefc0b481cdd30a205aef2d/docs/pages/filesystem-routing/%2BPage.mdx?plain=1#L98
35
+ // Enable hooks defined by vike-{react,vue,solid} such as +onBeforeRenderClient to be defined at the root directory. In other words, avoid following error:
36
+ // ```bash
37
+ // [11:09:43.072][/test-preview.test.ts][npm run preview][stderr] Error: [vike][Wrong Usage] /+onBeforeRenderClient.ts sets the value of the config onBeforeRenderClient which is a custom config that is defined with https://vike.dev/meta at a path that doesn't apply to / — see https://vike.dev/config#inheritance
38
+ // ```
41
39
  'pages',
42
40
  ]);
43
41
  }
@@ -9,10 +9,10 @@ import type { GlobalContextServerInternal } from '../node/runtime/globalContext.
9
9
  import type { GlobalContextClientInternal } from '../client/runtime-client-routing/globalContext.js';
10
10
  import { type Hook } from './hooks/getHook.js';
11
11
  declare const getGlobalContextSyncErrMsg = "The global context isn't set yet, call getGlobalContextSync() later or use getGlobalContext() instead.";
12
- declare function createGlobalContextShared<GlobalContextAddendum extends object>(virtualFileExports: unknown, globalObject: {
12
+ declare function createGlobalContextShared<GlobalContextAddendum extends Record<string, any>>(virtualFileExports: unknown, globalObject: {
13
13
  globalContext?: Record<string, unknown>;
14
14
  onCreateGlobalContextHooks?: Hook[];
15
- }, addGlobalContext?: (globalContext: GlobalContextBase) => Promise<GlobalContextAddendum>): Promise<{
15
+ }, addGlobalContextAsync?: (globalContext: GlobalContextBase) => Promise<GlobalContextAddendum>, addGlobalContextSync?: (globalContext: GlobalContextBase) => GlobalContextAddendum): Promise<{
16
16
  /**
17
17
  * Useful for distinguishing `globalContext` from other objects and narrowing down TypeScript unions.
18
18
  *
@@ -35,7 +35,7 @@ declare function createGlobalContextShared<GlobalContextAddendum extends object>
35
35
  pages: {
36
36
  [k: string]: import("./page-configs/resolveVikeConfigPublic.js").VikeConfigPublicPageEager;
37
37
  };
38
- } & Awaited<GlobalContextAddendum>>;
38
+ } & GlobalContextAddendum>;
39
39
  type GlobalContextBasePublic = Pick<GlobalContextBase, 'config' | 'pages' | 'isGlobalContext'>;
40
40
  type GlobalContextBase = ReturnType<typeof createGlobalContextBase>;
41
41
  declare function createGlobalContextBase(virtualFileExports: unknown): {
@@ -7,10 +7,24 @@ import { execHookGlobal } from './hooks/execHook.js';
7
7
  import { prepareGlobalContextForPublicUsage } from './prepareGlobalContextForPublicUsage.js';
8
8
  import { getHookFromPageConfigGlobalCumulative } from './hooks/getHook.js';
9
9
  const getGlobalContextSyncErrMsg = "The global context isn't set yet, call getGlobalContextSync() later or use getGlobalContext() instead.";
10
- async function createGlobalContextShared(virtualFileExports, globalObject, addGlobalContext) {
10
+ async function createGlobalContextShared(virtualFileExports, globalObject, addGlobalContextAsync, addGlobalContextSync) {
11
11
  const globalContext = createGlobalContextBase(virtualFileExports);
12
- const globalContextAddendum = await addGlobalContext?.(globalContext);
13
- objectAssign(globalContext, globalContextAddendum);
12
+ let isNewGlobalContext;
13
+ if (!globalObject.globalContext) {
14
+ globalObject.globalContext = globalContext;
15
+ isNewGlobalContext = false;
16
+ }
17
+ else {
18
+ isNewGlobalContext = true;
19
+ }
20
+ if (addGlobalContextSync && globalContext._pageConfigs.length > 0) {
21
+ const globalContextAddendum = addGlobalContextSync?.(globalContext);
22
+ objectAssign(globalContext, globalContextAddendum);
23
+ }
24
+ else {
25
+ const globalContextAddendum = await addGlobalContextAsync?.(globalContext);
26
+ objectAssign(globalContext, globalContextAddendum);
27
+ }
14
28
  const onCreateGlobalContextHooks = getHookFromPageConfigGlobalCumulative(globalContext._pageConfigGlobal, 'onCreateGlobalContext');
15
29
  let hooksCalled = false;
16
30
  if (!hooksAreEqual(globalObject.onCreateGlobalContextHooks ?? [], onCreateGlobalContextHooks)) {
@@ -18,10 +32,7 @@ async function createGlobalContextShared(virtualFileExports, globalObject, addGl
18
32
  await execHookGlobal('onCreateGlobalContext', globalContext._pageConfigGlobal, null, globalContext, prepareGlobalContextForPublicUsage);
19
33
  hooksCalled = true;
20
34
  }
21
- if (!globalObject.globalContext) {
22
- globalObject.globalContext = globalContext;
23
- }
24
- else {
35
+ if (isNewGlobalContext) {
25
36
  // Singleton: ensure all `globalContext` user-land references are preserved & updated.
26
37
  if (hooksCalled) {
27
38
  objectReplace(globalObject.globalContext, globalContext);
@@ -1,4 +1,5 @@
1
1
  export { loadPageRoutes };
2
+ export { loadPageRoutesSync };
2
3
  export type { PageRoutes };
3
4
  export type { RouteType };
4
5
  import type { PageFile } from '../getPageFiles.js';
@@ -28,3 +29,7 @@ declare function loadPageRoutes(pageFilesAll: PageFile[], pageConfigs: PageConfi
28
29
  pageRoutes: PageRoutes;
29
30
  onBeforeRouteHook: null | Hook;
30
31
  }>;
32
+ declare function loadPageRoutesSync(pageFilesAll: PageFile[], pageConfigs: PageConfigRuntime[], pageConfigGlobal: PageConfigGlobalRuntime, allPageIds: string[]): {
33
+ pageRoutes: PageRoutes;
34
+ onBeforeRouteHook: null | Hook;
35
+ };
@@ -1,4 +1,5 @@
1
1
  export { loadPageRoutes };
2
+ export { loadPageRoutesSync };
2
3
  import { isErrorPageId } from '../error-page.js';
3
4
  import { assert, assertUsage, hasProp, slice } from './utils.js';
4
5
  import { deduceRouteStringFromFilesystemPath } from './deduceRouteStringFromFilesystemPath.js';
@@ -10,8 +11,13 @@ import { getHookFromPageConfigGlobal, getHookTimeoutDefault } from '../hooks/get
10
11
  async function loadPageRoutes(
11
12
  // Remove all arguments and use GlobalContextServerInternal instead?
12
13
  pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds) {
13
- // TO-DO/next-major-release: remove & make this function sync
14
+ // TO-DO/next-major-release: remove this line, remove this function, rename loadPageRoutesSync() to loadPageRoutes()
14
15
  await Promise.all(pageFilesAll.filter((p) => p.fileType === '.page.route').map((p) => p.loadFile?.()));
16
+ return loadPageRoutesSync(pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds);
17
+ }
18
+ function loadPageRoutesSync(
19
+ // Remove all arguments and use GlobalContextServerInternal instead?
20
+ pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds) {
15
21
  const { onBeforeRouteHook, filesystemRoots } = getGlobalHooks(pageFilesAll, pageConfigs, pageConfigGlobal);
16
22
  const pageRoutes = getPageRoutes(filesystemRoots, pageFilesAll, pageConfigs, allPageIds);
17
23
  return { pageRoutes, onBeforeRouteHook };
@@ -508,6 +508,12 @@ type ConfigBuiltIn = {
508
508
  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
509
509
  */
510
510
  cacheControl?: string;
511
+ /**
512
+ * Add HTTP headers to the HTTP response.
513
+ *
514
+ * https://vike.dev/headers#response
515
+ */
516
+ headersResponse?: HeadersInit;
511
517
  /**
512
518
  * Make development/preview server available over LAN and public addresses.
513
519
  *
@@ -561,6 +567,7 @@ type ConfigBuiltInResolved = {
561
567
  redirects?: Record<string, string>[];
562
568
  prerender?: Exclude<Config['prerender'], ImportString | undefined>[];
563
569
  middleware?: Function[];
570
+ headersResponse?: HeadersInit[];
564
571
  };
565
572
  type ConfigMeta = Record<string, ConfigDefinition>;
566
573
  type ImportString = `import:${string}`;
@@ -81,7 +81,7 @@ type PageContextBuiltInCommon<Data> = {
81
81
  */
82
82
  urlOriginal: string;
83
83
  /**
84
- * The HTTP Headers of the incoming HTTP Request.
84
+ * The HTTP request headers.
85
85
  *
86
86
  * As a string object normalized by Vike.
87
87
  *
@@ -90,7 +90,7 @@ type PageContextBuiltInCommon<Data> = {
90
90
  */
91
91
  headers: Record<string, string> | null;
92
92
  /**
93
- * The HTTP Headers of the incoming HTTP Request.
93
+ * The HTTP request headers.
94
94
  *
95
95
  * The original object provided by the server.
96
96
  *
@@ -98,6 +98,12 @@ type PageContextBuiltInCommon<Data> = {
98
98
  * https://vike.dev/pageContext#headersOriginal
99
99
  */
100
100
  headersOriginal?: unknown;
101
+ /**
102
+ * The HTTP response headers.
103
+ *
104
+ * https://vike.dev/headers#response
105
+ */
106
+ headersResponse: Headers;
101
107
  /** If an error occurs, whether the error is a `404 Page Not Found`.
102
108
  *
103
109
  * https://vike.dev/error-page
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.235-commit-8f42b16";
1
+ export declare const PROJECT_VERSION: "0.4.235-commit-9b9289b";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.235-commit-8f42b16';
2
+ export const PROJECT_VERSION = '0.4.235-commit-9b9289b';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.235-commit-8f42b16",
3
+ "version": "0.4.235-commit-9b9289b",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {