vike 0.4.247-commit-87e5f2f → 0.4.247-commit-1250e38

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 (42) hide show
  1. package/dist/client/runtime-client-routing/getPageContext.js +1 -0
  2. package/dist/node/api/dev.js +2 -1
  3. package/dist/node/vite/index.js +2 -2
  4. package/dist/node/vite/plugins/pluginAssertFileEnv.d.ts +3 -0
  5. package/dist/node/vite/plugins/{pluginFileEnv.js → pluginAssertFileEnv.js} +44 -39
  6. package/dist/node/vite/plugins/pluginCommon/assertResolveAlias.js +1 -1
  7. package/dist/node/vite/plugins/pluginDev/optimizeDeps.d.ts +15 -0
  8. package/dist/node/vite/plugins/pluginDev/{determineOptimizeDeps.js → optimizeDeps.js} +45 -4
  9. package/dist/node/vite/plugins/pluginDev.d.ts +1 -1
  10. package/dist/node/vite/plugins/pluginDev.js +3 -19
  11. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFilePageEntry.js +1 -1
  12. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +3 -2
  13. package/dist/node/vite/plugins/pluginVirtualFiles.js +11 -9
  14. package/dist/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +8 -0
  15. package/dist/node/vite/shared/resolveVikeConfigInternal.js +5 -4
  16. package/dist/server/runtime/globalContext.d.ts +0 -2
  17. package/dist/server/runtime/globalContext.js +69 -50
  18. package/dist/server/runtime/renderPageServer/execHookServer.js +9 -2
  19. package/dist/server/runtime/renderPageServer.js +6 -9
  20. package/dist/server/utils.d.ts +1 -1
  21. package/dist/server/utils.js +1 -1
  22. package/dist/shared-server-client/assertVirtualFileExports.d.ts +2 -0
  23. package/dist/shared-server-client/assertVirtualFileExports.js +16 -0
  24. package/dist/shared-server-client/createGlobalContextShared.js +44 -40
  25. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.js +2 -0
  26. package/dist/shared-server-client/page-configs/loadAndParseVirtualFilePageEntry.js +9 -5
  27. package/dist/shared-server-node/getFileSuffixes.d.ts +6 -0
  28. package/dist/shared-server-node/getFileSuffixes.js +22 -0
  29. package/dist/shared-server-node/getVikeConfigError.d.ts +9 -0
  30. package/dist/shared-server-node/getVikeConfigError.js +4 -1
  31. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  32. package/dist/utils/PROJECT_VERSION.js +1 -1
  33. package/dist/utils/assertSetup.js +3 -3
  34. package/dist/utils/debug.d.ts +1 -1
  35. package/dist/utils/debug.js +1 -0
  36. package/dist/utils/getBetterError.js +3 -0
  37. package/dist/utils/isNonRunnableDevProcess.d.ts +2 -0
  38. package/dist/utils/{isNonRunnableDev.js → isNonRunnableDevProcess.js} +2 -2
  39. package/package.json +3 -3
  40. package/dist/node/vite/plugins/pluginDev/determineOptimizeDeps.d.ts +0 -3
  41. package/dist/node/vite/plugins/pluginFileEnv.d.ts +0 -3
  42. package/dist/utils/isNonRunnableDev.d.ts +0 -2
@@ -2,6 +2,7 @@ export { getPageContext };
2
2
  export { providePageContext };
3
3
  // TO-DO/eventually: create new setting `+asyncHook: true` that sets the default value of the `asyncHook` parameter below to `true`
4
4
  // TODO/next-release: update vike-{react,vue,solid} usage
5
+ // TODO/next-release: contact Da-Jin about `window.history.state?.vike` https://vike.dev/navigate#history-pushstate
5
6
  import { getPageContext_sync, providePageContext } from '../../shared-server-client/hooks/execHook.js';
6
7
  import { getPageContextClient } from './renderPageClient.js';
7
8
  function getPageContext({ asyncHook } = {}) {
@@ -3,9 +3,10 @@ export { dev };
3
3
  export { startupLog };
4
4
  import { prepareViteApiCall } from './prepareViteApiCall.js';
5
5
  import { createServer } from 'vite';
6
- import { assert, colorVike, colorVite, PROJECT_VERSION } from './utils.js';
6
+ import { assert, assertIsNotProductionRuntime, colorVike, colorVite, PROJECT_VERSION } from './utils.js';
7
7
  import pc from '@brillout/picocolors';
8
8
  import { processStartupLog } from '../vite/shared/loggerVite.js';
9
+ assertIsNotProductionRuntime();
9
10
  /**
10
11
  * Programmatically trigger `$ vike dev`
11
12
  *
@@ -17,7 +17,7 @@ import { pluginSetGlobalContext } from './plugins/pluginSetGlobalContext.js';
17
17
  import { pluginCommon } from './plugins/pluginCommon.js';
18
18
  import { pluginBaseUrls } from './plugins/pluginBaseUrls.js';
19
19
  import { pluginReplaceConstantsEnvVars } from './plugins/pluginReplaceConstantsEnvVars.js';
20
- import { pluginFileEnv } from './plugins/pluginFileEnv.js';
20
+ import { pluginAssertFileEnv } from './plugins/pluginAssertFileEnv.js';
21
21
  import { pluginWorkaroundCssModuleHmr } from './plugins/pluginWorkaroundCssModuleHmr.js';
22
22
  import { pluginWorkaroundVite6HmrRegression } from './plugins/pluginWorkaroundVite6HmrRegression.js';
23
23
  import { pluginReplaceConstantsPageContext } from './plugins/pluginReplaceConstantsPageContext.js';
@@ -53,7 +53,7 @@ function plugin(vikeVitePluginOptions = {}) {
53
53
  ...pluginSetGlobalContext(),
54
54
  ...pluginBaseUrls(),
55
55
  ...pluginReplaceConstantsEnvVars(),
56
- ...pluginFileEnv(),
56
+ ...pluginAssertFileEnv(),
57
57
  ...pluginWorkaroundCssModuleHmr(),
58
58
  ...pluginWorkaroundVite6HmrRegression(),
59
59
  ...pluginReplaceConstantsPageContext(),
@@ -0,0 +1,3 @@
1
+ export { pluginAssertFileEnv };
2
+ import type { Plugin } from 'vite';
3
+ declare function pluginAssertFileEnv(): Plugin[];
@@ -1,4 +1,4 @@
1
- export { pluginFileEnv };
1
+ export { pluginAssertFileEnv };
2
2
  import { assert, assertUsage, assertWarning, capitalizeFirstLetter, isFilePathAbsolute, joinEnglish, rollupSourceMapRemove, } from '../utils.js';
3
3
  import { extractAssetsRE } from './pluginExtractAssets.js';
4
4
  import { extractExportNamesRE } from './pluginExtractExportNames.js';
@@ -8,26 +8,26 @@ import { getExportNames } from '../shared/parseEsModule.js';
8
8
  import { normalizeId } from '../shared/normalizeId.js';
9
9
  import { isV1Design } from '../shared/resolveVikeConfigInternal.js';
10
10
  import { isViteServerSide, isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
11
- const skipNodeModules = '/node_modules/'; // Only apply `.server.js` and `.client.js` to user files
11
+ import { suffixesAssertFileEnv } from '../../../shared-server-node/getFileSuffixes.js';
12
+ const envS = suffixesAssertFileEnv;
13
+ const skipNodeModules = '/node_modules/'; // Only assert `.server.js`, `.client.js` and `.ssr.js` for user files
12
14
  const filterRolldown = {
13
15
  id: {
14
- include: ['client', 'server'].map((env) => `**/*${getSuffix(env)}*`),
16
+ include: envS.map((env) => `**/*${getSuffix(env)}*`),
15
17
  exclude: [`**${skipNodeModules}**`],
16
18
  },
17
19
  };
18
20
  const filterFunction = (id) => {
19
21
  if (id.includes(skipNodeModules))
20
22
  return false;
21
- if (!id.includes(getSuffix('client')) && !id.includes(getSuffix('server')))
22
- return false;
23
- return true;
23
+ return envS.some((suffix) => id.includes(getSuffix(suffix)));
24
24
  };
25
- function pluginFileEnv() {
25
+ function pluginAssertFileEnv() {
26
26
  let config;
27
27
  let viteDevServer;
28
28
  return [
29
29
  {
30
- name: 'vike:pluginFileEnv',
30
+ name: 'vike:pluginAssertFileEnv',
31
31
  load: {
32
32
  filter: filterRolldown,
33
33
  handler(id, options) {
@@ -68,7 +68,7 @@ function pluginFileEnv() {
68
68
  return;
69
69
  const { importers } = this.getModuleInfo(id);
70
70
  // Throwing a verbose error doesn't waste client-side KBs as dynamic imports are code split.
71
- const errMsg = getErrorMessage(id, isServerSide, importers, false, true);
71
+ const errMsg = getErrMsg(id, isServerSide, importers, false, config, true);
72
72
  // We have to inject empty exports to avoid Rollup complaining about missing exports, see https://gist.github.com/brillout/5ea45776e65bd65100a52ecd7bfda3ff
73
73
  const { exportNames } = await getExportNames(code);
74
74
  return rollupSourceMapRemove([
@@ -111,7 +111,7 @@ function pluginFileEnv() {
111
111
  function assertFileEnv(moduleId, isServerSide, importers, onlyWarn) {
112
112
  if (!isWrongEnv(moduleId, isServerSide))
113
113
  return;
114
- const errMsg = getErrorMessage(moduleId, isServerSide, importers, onlyWarn, false);
114
+ const errMsg = getErrMsg(moduleId, isServerSide, importers, onlyWarn, config, false);
115
115
  if (onlyWarn) {
116
116
  assertWarning(false, errMsg, { onlyOnce: true });
117
117
  }
@@ -119,38 +119,43 @@ function pluginFileEnv() {
119
119
  assertUsage(false, errMsg);
120
120
  }
121
121
  }
122
- function getErrorMessage(moduleId, isServerSide, importers, onlyWarn, noColor) {
123
- const modulePath = getModulePath(moduleId);
124
- const envActual = isServerSide ? 'server' : 'client';
125
- const envExpect = isServerSide ? 'client' : 'server';
126
- let errMsg;
127
- let modulePathPretty = getFilePathToShowToUserModule(modulePath, config);
128
- if (!noColor) {
129
- const suffix = getSuffix(envExpect);
130
- modulePathPretty = modulePathPretty.replaceAll(suffix, pc.bold(suffix));
131
- }
132
- errMsg = `${capitalizeFirstLetter(envExpect)}-only file ${modulePathPretty} (https://vike.dev/file-env) imported on the ${envActual}-side`;
133
- {
134
- const importPaths = importers
135
- .filter((importer) =>
136
- // Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
137
- isFilePathAbsolute(importer))
138
- .map((importer) => getFilePathToShowToUserModule(importer, config))
139
- .map((importPath) => pc.cyan(importPath));
140
- if (importPaths.length > 0) {
141
- errMsg += ` by ${joinEnglish(importPaths, 'and')}`;
142
- }
143
- }
144
- if (onlyWarn) {
145
- errMsg += ". This is potentially a security issue and Vike won't allow you to build your app for production.";
146
- }
147
- return errMsg;
148
- }
149
122
  }
150
123
  function isWrongEnv(moduleId, isServerSide) {
151
124
  const modulePath = getModulePath(moduleId);
152
- const suffixWrong = getSuffix(isServerSide ? 'client' : 'server');
153
- return modulePath.includes(suffixWrong);
125
+ if (isServerSide) {
126
+ // On server-side, .client. is wrong
127
+ return modulePath.includes(getSuffix('client'));
128
+ }
129
+ else {
130
+ // On client-side, both .server. and .ssr. are wrong
131
+ return modulePath.includes(getSuffix('server')) || modulePath.includes(getSuffix('ssr'));
132
+ }
133
+ }
134
+ function getErrMsg(moduleId, isServerSide, importers, onlyWarn, config, noColor) {
135
+ const envActual = isServerSide ? 'server' : 'client';
136
+ const envExpect = isServerSide ? 'client' : 'server';
137
+ const modulePath = getModulePath(moduleId);
138
+ let modulePathPretty = getFilePathToShowToUserModule(modulePath, config);
139
+ if (!noColor) {
140
+ const suffix = modulePath.includes(getSuffix('ssr')) ? getSuffix('ssr') : getSuffix(envExpect);
141
+ modulePathPretty = modulePathPretty.replaceAll(suffix, pc.bold(suffix));
142
+ }
143
+ let errMsg = `${capitalizeFirstLetter(envExpect)}-only file ${modulePathPretty} (https://vike.dev/file-env) imported on the ${envActual}-side`;
144
+ {
145
+ const importPaths = importers
146
+ .filter((importer) =>
147
+ // Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
148
+ isFilePathAbsolute(importer))
149
+ .map((importer) => getFilePathToShowToUserModule(importer, config))
150
+ .map((importPath) => pc.cyan(importPath));
151
+ if (importPaths.length > 0) {
152
+ errMsg += ` by ${joinEnglish(importPaths, 'and')}`;
153
+ }
154
+ }
155
+ if (onlyWarn) {
156
+ errMsg += ". This is potentially a security issue and Vike won't allow you to build your app for production.";
157
+ }
158
+ return errMsg;
154
159
  }
155
160
  function skip(id, userRootDir) {
156
161
  assert(filterFunction(id));
@@ -56,7 +56,7 @@ function assertResolveAlias(config) {
56
56
  assertUsage(find !== '', msg);
57
57
  }
58
58
  // Ensure path alias are distinguishable from npm package names, which is needed by:
59
- // - determineOptimizeDeps()
59
+ // - resolveOptimizeDeps()
60
60
  // - extractAssets
61
61
  // - in general: using un-distinguishable path aliases is asking for trouble
62
62
  if (!isPathAliasRecommended(find)) {
@@ -0,0 +1,15 @@
1
+ export { optimizeDeps };
2
+ export { resolveOptimizeDeps };
3
+ import type { ResolvedConfig } from 'vite';
4
+ declare const optimizeDeps: {
5
+ readonly optimizeDeps: {
6
+ readonly exclude: ["vike/client", "vike/client/router"];
7
+ readonly include: ["vike > @brillout/json-serializer/parse", "vike > @brillout/json-serializer/stringify", "vike > @brillout/picocolors"];
8
+ };
9
+ readonly ssr: {
10
+ readonly optimizeDeps: {
11
+ readonly exclude: ["@brillout/import", "@brillout/json-serializer", "@brillout/picocolors", "@brillout/vite-plugin-server-entry", "vike"];
12
+ };
13
+ };
14
+ };
15
+ declare function resolveOptimizeDeps(config: ResolvedConfig): Promise<void>;
@@ -1,4 +1,5 @@
1
- export { determineOptimizeDeps };
1
+ export { optimizeDeps };
2
+ export { resolveOptimizeDeps };
2
3
  import { findPageFiles } from '../../shared/findPageFiles.js';
3
4
  import { assert, assertIsImportPathNpmPackage, createDebug, getNpmPackageName, isArray, isFilePathAbsoluteFilesystem, isVirtualFileId, requireResolveOptional, } from '../../utils.js';
4
5
  import { getVikeConfigInternal } from '../../shared/resolveVikeConfigInternal.js';
@@ -7,7 +8,8 @@ import { virtualFileIdGlobalEntryClientCR, virtualFileIdGlobalEntryClientSR, } f
7
8
  import { getFilePathResolved } from '../../shared/getFilePath.js';
8
9
  import { getConfigValueSourcesRelevant } from '../pluginVirtualFiles/getConfigValueSourcesRelevant.js';
9
10
  const debug = createDebug('vike:optimizeDeps');
10
- const WORKAROUND_LATE_DISCOVERY = [
11
+ // Add dependencies that cannot be discovered by Vite during the scanning phase
12
+ const LATE_DISCOVERED = [
11
13
  // Workaround for https://github.com/vitejs/vite-plugin-react/issues/650
12
14
  // - The issue was closed as completed with https://github.com/vitejs/vite/pull/20495 but it doesn't fix the issue and the workaround is still needed.
13
15
  // - TO-DO/eventually: try removing the workaround and see if the CI fails (at test/@cloudflare_vite-plugin/) — maybe the issue will get fixed at some point.
@@ -15,11 +17,47 @@ const WORKAROUND_LATE_DISCOVERY = [
15
17
  // Workaround for https://github.com/vikejs/vike/issues/2823#issuecomment-3514325487
16
18
  '@compiled/react/runtime',
17
19
  ];
18
- async function determineOptimizeDeps(config) {
20
+ const optimizeDeps = {
21
+ optimizeDeps: {
22
+ exclude: [
23
+ // We must exclude Vike's client runtime so it can import virtual modules
24
+ 'vike/client',
25
+ 'vike/client/router',
26
+ ],
27
+ include: [
28
+ // Avoid:
29
+ // ```
30
+ // 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
31
+ // 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
32
+ // ```
33
+ 'vike > @brillout/json-serializer/parse',
34
+ 'vike > @brillout/json-serializer/stringify',
35
+ 'vike > @brillout/picocolors',
36
+ ],
37
+ },
38
+ ssr: {
39
+ optimizeDeps: {
40
+ exclude: [
41
+ '@brillout/import',
42
+ '@brillout/json-serializer',
43
+ '@brillout/picocolors',
44
+ '@brillout/vite-plugin-server-entry',
45
+ 'vike',
46
+ ],
47
+ },
48
+ },
49
+ };
50
+ // Populate optimizeDeps with dynamic entries:
51
+ // - User's + files (i.e. Vike entries)
52
+ // - Late discovered dependencies (if they exist)
53
+ // - Make server environments inherit from ssr.optimizeDeps (it isn't the case by default)
54
+ async function resolveOptimizeDeps(config) {
19
55
  const vikeConfig = await getVikeConfigInternal();
20
56
  const { _pageConfigs: pageConfigs } = vikeConfig;
57
+ // Retrieve user's + files (i.e. Vike entries)
21
58
  const { entriesClient, entriesServer, includeClient, includeServer } = await getPageDeps(config, pageConfigs);
22
- WORKAROUND_LATE_DISCOVERY.forEach((dep) => {
59
+ // Add late discovered dependencies, if they exist
60
+ LATE_DISCOVERED.forEach((dep) => {
23
61
  const userRootDir = config.root;
24
62
  const resolved = requireResolveOptional({ importPath: dep, userRootDir, importerFilePath: null });
25
63
  const resolvedInsideRepo = resolved && resolved.startsWith(userRootDir);
@@ -39,8 +77,10 @@ async function determineOptimizeDeps(config) {
39
77
  includeServer.push(dep);
40
78
  }
41
79
  });
80
+ // Set optimizeDeps (client-side)
42
81
  config.optimizeDeps.include = add(config.optimizeDeps.include, includeClient);
43
82
  config.optimizeDeps.entries = add(config.optimizeDeps.entries, entriesClient);
83
+ // Set optimizeDeps (server-side)
44
84
  for (const envName in config.environments) {
45
85
  const env = config.environments[envName];
46
86
  if (env.consumer === 'server' && env.optimizeDeps.noDiscovery === false) {
@@ -48,6 +88,7 @@ async function determineOptimizeDeps(config) {
48
88
  env.optimizeDeps.entries = add(env.optimizeDeps.entries, entriesServer);
49
89
  }
50
90
  }
91
+ // Debug
51
92
  if (debug.isActivated)
52
93
  debug('optimizeDeps', {
53
94
  'config.optimizeDeps.entries': config.optimizeDeps.entries,
@@ -1,5 +1,5 @@
1
1
  export { pluginDev };
2
2
  export { logDockerHint };
3
- import type { Plugin, ResolvedConfig } from 'vite';
3
+ import { type Plugin, type ResolvedConfig } from 'vite';
4
4
  declare function pluginDev(): Plugin[];
5
5
  declare function logDockerHint(configHost: ResolvedConfig['server']['host']): void;
@@ -1,6 +1,6 @@
1
1
  export { pluginDev };
2
2
  export { logDockerHint };
3
- import { determineOptimizeDeps } from './pluginDev/determineOptimizeDeps.js';
3
+ import { optimizeDeps, resolveOptimizeDeps } from './pluginDev/optimizeDeps.js';
4
4
  import { determineFsAllowList } from './pluginDev/determineFsAllowList.js';
5
5
  import { addSsrMiddleware } from '../shared/addSsrMiddleware.js';
6
6
  import { applyDev, assertWarning, isDocker, isDebugError } from '../utils.js';
@@ -17,30 +17,14 @@ function pluginDev() {
17
17
  handler() {
18
18
  return {
19
19
  appType: 'custom',
20
- optimizeDeps: {
21
- exclude: [
22
- // We must exclude Vike's client runtime so it can import virtual modules
23
- 'vike/client',
24
- 'vike/client/router',
25
- ],
26
- include: [
27
- // Avoid:
28
- // ```
29
- // 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
30
- // 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
31
- // ```
32
- 'vike > @brillout/json-serializer/parse',
33
- 'vike > @brillout/json-serializer/stringify',
34
- 'vike > @brillout/picocolors',
35
- ],
36
- },
20
+ ...optimizeDeps,
37
21
  };
38
22
  },
39
23
  },
40
24
  configResolved: {
41
25
  async handler(config_) {
42
26
  config = config_;
43
- await determineOptimizeDeps(config);
27
+ await resolveOptimizeDeps(config);
44
28
  await determineFsAllowList(config);
45
29
  interceptViteLogs(config);
46
30
  logDockerHint(config.server.host);
@@ -25,7 +25,7 @@ async function generateVirtualFilePageEntry(id, isDev) {
25
25
  assert(pageConfig);
26
26
  }
27
27
  else {
28
- /* This assertion sometimes fail. It happens very seldom and I couldn't reproduce it (https://gist.github.com/brillout/9e212ce829f4d62a912ca163ffa8881a). I suspect some kind of HMR race condition.
28
+ /* This assertion sometimes fail. It happens very seldom and I couldn't reproduce it (https://gist.github.com/brillout/9e212ce829f4d62a912ca163ffa8881a). I suspect some kind of HMR race condition. UPDATE: [December 2024] This just happened at test/@cloudflare_vite-plugin/ — it isn't blocking, reloading the page fixes the issue.
29
29
  assert(pageConfig, { id, pageId })
30
30
  /*/
31
31
  if (!pageConfig)
@@ -3,6 +3,7 @@ export { getConfigValueSourceRelevantAnyEnv };
3
3
  export { isRuntimeEnvMatch };
4
4
  export { isConfigSourceValueNull };
5
5
  import { assert, assertIsNotBrowser } from '../../utils.js';
6
+ import { getFileSuffixes } from '../../../../shared-server-node/getFileSuffixes.js';
6
7
  assertIsNotBrowser();
7
8
  function getConfigValueSourcesRelevant(configName, runtimeEnv, pageConfig) {
8
9
  const configDef = pageConfig.configDefinitions[configName];
@@ -86,10 +87,10 @@ function isConfigSourceValueNull(source) {
86
87
  function applyFilenameSuffix(sourcesRelevant) {
87
88
  const getFileName = (source) => source.plusFile?.filePath.fileName ?? '';
88
89
  // Apply `clear`: truncate at first clear file
89
- const clearIndex = sourcesRelevant.findIndex((source) => getFileName(source).includes('.clear.'));
90
+ const clearIndex = sourcesRelevant.findIndex((source) => getFileSuffixes(getFileName(source)).includes('clear'));
90
91
  if (clearIndex !== -1)
91
92
  sourcesRelevant = sourcesRelevant.slice(0, clearIndex + 1);
92
93
  // Apply `default`: exclude defaults if any non-defaults exist, otherwise keep only first default
93
- const nonDefaults = sourcesRelevant.filter((source) => !getFileName(source).includes('.default.'));
94
+ const nonDefaults = sourcesRelevant.filter((source) => !getFileSuffixes(getFileName(source)).includes('default'));
94
95
  return nonDefaults.length > 0 ? nonDefaults : sourcesRelevant.slice(0, 1);
95
96
  }
@@ -8,10 +8,10 @@ import { reloadVikeConfig, isV1Design, getVikeConfigInternalOptional } from '../
8
8
  import pc from '@brillout/picocolors';
9
9
  import { logConfigInfo } from '../shared/loggerDev.js';
10
10
  import { getFilePathToShowToUserModule } from '../shared/getFilePath.js';
11
- import { isRunnable, updateUserFiles } from '../../../server/runtime/globalContext.js';
11
+ import { updateUserFiles } from '../../../server/runtime/globalContext.js';
12
12
  import { isPlusFile } from '../shared/resolveVikeConfigInternal/crawlPlusFiles.js';
13
13
  import { isTemporaryBuildFile } from '../shared/resolveVikeConfigInternal/transpileAndExecuteFile.js';
14
- import { getVikeConfigError } from '../../../shared-server-node/getVikeConfigError.js';
14
+ import { debugFileChange, getVikeConfigError } from '../../../shared-server-node/getVikeConfigError.js';
15
15
  const filterRolldown = {
16
16
  id: {
17
17
  include: new RegExp(`^(${escapeRegex(virtualFileIdPrefix1)}|${escapeRegex(virtualFileIdPrefix2)})`),
@@ -40,6 +40,7 @@ function pluginVirtualFiles() {
40
40
  },
41
41
  handleHotUpdate: {
42
42
  async handler(ctx) {
43
+ debugFileChange('handleHotUpdate()', ctx.file);
43
44
  try {
44
45
  return await handleHotUpdate(ctx, config);
45
46
  }
@@ -86,9 +87,11 @@ function handleFileAddRemove(server, config) {
86
87
  file = normalizePath(file);
87
88
  if (isTemporaryBuildFile(file))
88
89
  return;
90
+ const operation = isRemove ? 'removed' : 'created';
91
+ debugFileChange('server.watcher', file, operation);
89
92
  const { moduleGraph } = server;
90
93
  const isVikeConfigDep = await isVikeConfigDependency(file, moduleGraph);
91
- const reload = () => reloadConfig(file, config, isRemove ? 'removed' : 'created', server);
94
+ const reload = () => reloadConfig(file, config, operation, server);
92
95
  // Config code
93
96
  if (isVikeConfigDep && !isVikeConfigDep.isProcessedByVite) {
94
97
  reload();
@@ -127,6 +130,7 @@ function invalidateVikeVirtualFiles(server) {
127
130
  async function handleHotUpdate(ctx, config) {
128
131
  const { file, server } = ctx;
129
132
  const isVikeConfigDep = await isVikeConfigDependency(ctx.file, ctx.server.moduleGraph);
133
+ debugFileChange(isVikeConfigDep);
130
134
  if (isVikeConfigDep) {
131
135
  if (!isVikeConfigDep.isProcessedByVite) {
132
136
  /* Tailwind breaks this assertion, see https://github.com/vikejs/vike/discussions/1330#discussioncomment-7787238
@@ -141,11 +145,9 @@ async function handleHotUpdate(ctx, config) {
141
145
  }
142
146
  else {
143
147
  // Ensure we invalidate `file` *before* server.ssrLoadModule() in updateUserFiles()
144
- // Vite already invalidates it, but *after* handleHotUpdate() and thus after server.ssrLoadModule()
148
+ // Vite also invalidates it, but *after* handleHotUpdate() and thus after server.ssrLoadModule()
145
149
  ctx.modules.forEach((mod) => server.moduleGraph.invalidateModule(mod));
146
- if (isRunnable(server)) {
147
- await updateUserFiles();
148
- }
150
+ await updateUserFiles();
149
151
  }
150
152
  }
151
153
  }
@@ -172,12 +174,12 @@ async function isVikeConfigDependency(filePathAbsoluteFilesystem, moduleGraph) {
172
174
  return { isProcessedByVite: true };
173
175
  return null;
174
176
  }
175
- function reloadConfig(filePath, config, op, server) {
177
+ function reloadConfig(filePath, config, operation, server) {
176
178
  // Ensure server.ssrLoadModule() loads fresh Vike virtual files (`reloadConfig()` > `updateUserFiles()` > `server.ssrLoadModule()`)
177
179
  invalidateVikeVirtualFiles(server);
178
180
  {
179
181
  const filePathToShowToUserResolved = getFilePathToShowToUserModule(filePath, config);
180
- const msg = `${op} ${pc.dim(filePathToShowToUserResolved)}`;
182
+ const msg = `${operation} ${pc.dim(filePathToShowToUserResolved)}`;
181
183
  logConfigInfo(msg, 'info');
182
184
  }
183
185
  reloadVikeConfig();
@@ -114,6 +114,14 @@ const configDefinitionsBuiltIn = {
114
114
  .flat(1)
115
115
  // Server-only
116
116
  .filter((source) => !source.configEnv.client)
117
+ // Exclude `.ssr.js` hooks (they don't require pageContext.json requests)
118
+ .filter((source) => {
119
+ const { definedAt } = source;
120
+ if ('filePathAbsoluteVite' in definedAt && definedAt.filePathAbsoluteVite.includes('.ssr.')) {
121
+ return false;
122
+ }
123
+ return true;
124
+ })
117
125
  // Config value isn't `null`
118
126
  .filter((source) => !isConfigSourceValueNull(source));
119
127
  return sources.length > 0;
@@ -12,6 +12,7 @@ export { getConfigDefinitionOptional };
12
12
  export { getVikeConfigFromCliOrEnv };
13
13
  import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, includes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, assertKeys, objectKeys, objectFromEntries, unique, isCallable, makeFirst, lowerFirst, makeLast, genPromise, checkType, objectAssign, getGlobalObject, } from '../utils.js';
14
14
  import { configDefinitionsBuiltIn, } from './resolveVikeConfigInternal/configDefinitionsBuiltIn.js';
15
+ import { getFileSuffixes } from '../../../shared-server-node/getFileSuffixes.js';
15
16
  import { getLocationId, getFilesystemRouteString, getFilesystemRouteDefinedBy, isInherited, sortAfterInheritanceOrder, applyFilesystemRoutingRootEffect, } from './resolveVikeConfigInternal/filesystemRouting.js';
16
17
  import { getViteDevServer, vikeConfigErrorRecoverMsg } from '../../../server/runtime/globalContext.js';
17
18
  import { logConfigInfo, logErrorServerDev } from './loggerDev.js';
@@ -1066,16 +1067,16 @@ function getConfVal(plusFile, configName) {
1066
1067
  function resolveConfigEnv(configEnv, filePath) {
1067
1068
  const configEnvResolved = { ...configEnv };
1068
1069
  if (filePath.filePathAbsoluteFilesystem) {
1069
- const { fileName } = filePath;
1070
- if (fileName.includes('.server.')) {
1070
+ const suffixes = getFileSuffixes(filePath.fileName);
1071
+ if (suffixes.includes('ssr') || suffixes.includes('server')) {
1071
1072
  configEnvResolved.server = true;
1072
1073
  configEnvResolved.client = false;
1073
1074
  }
1074
- else if (fileName.includes('.client.')) {
1075
+ else if (suffixes.includes('client')) {
1075
1076
  configEnvResolved.client = true;
1076
1077
  configEnvResolved.server = false;
1077
1078
  }
1078
- else if (fileName.includes('.shared.')) {
1079
+ else if (suffixes.includes('shared')) {
1079
1080
  configEnvResolved.server = true;
1080
1081
  configEnvResolved.client = true;
1081
1082
  }
@@ -17,7 +17,6 @@ export { setGlobalContext_prodBuildEntry };
17
17
  export { clearGlobalContext };
18
18
  export { assertBuildInfo };
19
19
  export { updateUserFiles };
20
- export { isRunnable };
21
20
  export { vikeConfigErrorRecoverMsg };
22
21
  export type { BuildInfo };
23
22
  export type { GlobalContextServerInternal };
@@ -466,4 +465,3 @@ declare function createGlobalContext(virtualFileExportsGlobalEntry: unknown): Pr
466
465
  prerenderContext: PrerenderContext | undefined;
467
466
  }>;
468
467
  declare function clearGlobalContext(): void;
469
- declare function isRunnable(viteDevServer: ViteDevServer): boolean;
@@ -19,7 +19,6 @@ export { setGlobalContext_prodBuildEntry }; // production entry
19
19
  export { clearGlobalContext };
20
20
  export { assertBuildInfo };
21
21
  export { updateUserFiles };
22
- export { isRunnable };
23
22
  export { vikeConfigErrorRecoverMsg };
24
23
  // The core logic revolves around:
25
24
  // - virtualFileExportsGlobalEntry is the main requirement
@@ -29,7 +28,7 @@ export { vikeConfigErrorRecoverMsg };
29
28
  // - Without vike-server it's manually loaded here using importServerProductionEntry() which uses @brillout/vite-plugin-server-entry's autoImporter or crawler
30
29
  // - In development: globalObject.viteDevServer which is Vite's development server
31
30
  // - globalObject.viteDevServer is used by updateUserFiles() which then sets virtualFileExportsGlobalEntry
32
- import { assert, onSetupRuntime, assertUsage, assertWarning, isPlainObject, objectReplace, isObject, hasProp, getGlobalObject, genPromise, createDebug, checkType, PROJECT_VERSION, getViteRPC, isRunnableDevEnvironment, assertIsNotBrowser, isNonRunnableDev, objectAssign, setNodeEnvProductionIfUndefined, } from '../utils.js';
31
+ import { assert, onSetupRuntime, assertUsage, assertWarning, isPlainObject, objectReplace, isObject, hasProp, getGlobalObject, genPromise, createDebug, checkType, PROJECT_VERSION, getViteRPC, isRunnableDevEnvironment, assertIsNotBrowser, isNonRunnableDevProcess, objectAssign, setNodeEnvProductionIfUndefined, } from '../utils.js';
33
32
  import { importServerProductionEntry } from '@brillout/vite-plugin-server-entry/runtime';
34
33
  import { virtualFileIdGlobalEntryServer } from '../../shared-server-node/virtualFileId.js';
35
34
  import pc from '@brillout/picocolors';
@@ -39,7 +38,7 @@ import { resolveBase } from '../../shared-server-node/resolveBase.js';
39
38
  import { createGlobalContextShared, getGlobalContextSyncErrMsg, } from '../../shared-server-client/createGlobalContextShared.js';
40
39
  import { prepareGlobalContextForPublicUsage } from '../../shared-server-client/prepareGlobalContextForPublicUsage.js';
41
40
  import { logRuntimeError, logRuntimeInfo } from './loggerRuntime.js';
42
- import { getVikeConfigErrorBuild, setVikeConfigError } from '../../shared-server-node/getVikeConfigError.js';
41
+ import { debugFileChange, getVikeConfigErrorBuild, setVikeConfigError, } from '../../shared-server-node/getVikeConfigError.js';
43
42
  import { getVikeApiOperation } from '../../shared-server-node/api-context.js';
44
43
  import { hasAlreadyLogged } from './logErrorServer.js';
45
44
  const debug = createDebug('vike:globalContext');
@@ -130,6 +129,7 @@ function getGlobalContextForPublicUsage() {
130
129
  }
131
130
  async function setGlobalContext_viteDevServer(viteDevServer) {
132
131
  debug('setGlobalContext_viteDevServer()');
132
+ assert(!isNonRunnableDevProcess()); // if `viteDevServer` exists => cannot be inside a non-runnable process
133
133
  // We cannot cache globalObject.viteDevServer because it's fully replaced when the user modifies vite.config.js => Vite's dev server is fully reloaded and a new viteDevServer replaces the previous one.
134
134
  if (!globalObject.viteDevServer) {
135
135
  assertIsNotInitializedYet();
@@ -137,12 +137,10 @@ async function setGlobalContext_viteDevServer(viteDevServer) {
137
137
  assert(globalObject.viteConfig);
138
138
  globalObject.viteDevServer = viteDevServer;
139
139
  globalObject.viteDevServerPromiseResolve(viteDevServer);
140
- if (isRunnable(viteDevServer)) {
141
- const { success } = await updateUserFiles();
142
- if (!success)
143
- return;
144
- assertGlobalContextIsDefined();
145
- }
140
+ const { success } = await updateUserFiles();
141
+ if (!success)
142
+ return;
143
+ assertGlobalContextIsDefined();
146
144
  }
147
145
  function setGlobalContext_viteConfig(viteConfig, viteConfigRuntime) {
148
146
  if (globalObject.viteConfig)
@@ -210,7 +208,7 @@ async function initGlobalContext() {
210
208
  await globalObject.viteDevServerPromise;
211
209
  }
212
210
  else {
213
- assert(isNonRunnableDev());
211
+ assert(isNonRunnableDevProcess());
214
212
  await updateUserFiles();
215
213
  }
216
214
  assert(globalObject.waitForUserFilesUpdate);
@@ -268,7 +266,7 @@ async function loadProdBuildEntry(outDir) {
268
266
  // https://github.com/vikejs/vike/blob/8c350e8105a626469e87594d983090919e82099b/packages/vike/node/vite/plugins/pluginBuild/pluginProdBuildEntry.ts#L47
269
267
  async function setGlobalContext_prodBuildEntry(prodBuildEntry) {
270
268
  debug('setGlobalContext_prodBuildEntry()');
271
- assert(!isNonRunnableDev());
269
+ assert(!isNonRunnableDevProcess());
272
270
  assertProdBuildEntry(prodBuildEntry);
273
271
  setNodeEnvProductionIfUndefined();
274
272
  globalObject.prodBuildEntry = prodBuildEntry;
@@ -307,48 +305,28 @@ function assertVersionAtBuildTime(versionAtBuildTime) {
307
305
  const pretty = (version) => pc.bold(`vike@${version}`);
308
306
  assertUsage(versionAtBuildTime === versionAtRuntime, `Re-build your app (you're using ${pretty(versionAtRuntime)} but your app was built with ${pretty(versionAtBuildTime)})`);
309
307
  }
310
- // TODO: recover from +onCreateGlobalContext runtime error doesn't work
311
308
  async function updateUserFiles() {
312
- debug('updateUserFiles()');
309
+ debugUpdate();
313
310
  assert(!isProd());
311
+ const { viteDevServer } = globalObject;
312
+ const isRunnableServer = !!viteDevServer && isRunnableDevServer(viteDevServer);
313
+ const isNonRunnableProcess = isNonRunnableDevProcess();
314
+ if (!isRunnableServer && !isNonRunnableProcess) {
315
+ // Not the runtime process — it's the Vite process and not the non-runnable process
316
+ debugUpdate('=> aborted: not runtime');
317
+ return { success: false };
318
+ }
314
319
  const { promise, resolve } = genPromise();
315
320
  globalObject.waitForUserFilesUpdate = promise;
316
321
  globalObject.waitForUserFilesUpdateResolve ?? (globalObject.waitForUserFilesUpdateResolve = []);
317
322
  globalObject.waitForUserFilesUpdateResolve.push(resolve);
318
- const onError = (err) => {
319
- if (
320
- // We must check whether the error was already logged to avoid printing it twice, e.g. when +onCreateGlobalContext.js has a syntax error
321
- !hasAlreadyLogged(err)) {
322
- logRuntimeError(err, null);
323
- }
324
- setVikeConfigError({ errorRuntime: { err } });
325
- globalObject.vikeConfigHasRuntimeError = true;
326
- return { success: false };
327
- };
328
- const onSuccess = () => {
329
- if (globalObject.vikeConfigHasRuntimeError) {
330
- assert(logRuntimeInfo); // always defined in dev
331
- logRuntimeInfo(vikeConfigErrorRecoverMsg, null, 'error-resolve');
332
- }
333
- globalObject.vikeConfigHasRuntimeError = false;
334
- setVikeConfigError({ errorRuntime: false });
335
- globalObject.waitForUserFilesUpdateResolve.forEach((resolve) => resolve());
336
- globalObject.waitForUserFilesUpdateResolve = [];
337
- resolve();
338
- return { success: true };
339
- };
340
- const isOutdated = () =>
341
- // There is a newer call — let the new call supersede the old one.
342
- // We deliberately swallow the intermetidate state (including any potential error) — it's now outdated and has existed only for a very short period of time.
343
- globalObject.waitForUserFilesUpdate !== promise ||
344
- // Avoid race condition: abort if there is a new globalObject.viteDevServer (happens when vite.config.js is modified => Vite's dev server is fully reloaded).
345
- viteDevServer !== globalObject.viteDevServer;
346
- const { viteDevServer } = globalObject;
347
323
  let hasError = false;
348
324
  let virtualFileExportsGlobalEntry;
349
325
  let err;
350
- if (viteDevServer) {
351
- assert(isRunnable(viteDevServer));
326
+ if (isRunnableServer) {
327
+ assert(viteDevServer);
328
+ assert(isRunnableDevServer(viteDevServer));
329
+ assert(!isNonRunnableProcess);
352
330
  /* We don't use runner.import() yet, because as of vite@7.0.6 (July 2025) runner.import() unexpectedly invalidates the module graph, which is a unexpected behavior that doesn't happen with ssrLoadModule()
353
331
  // Vite 6
354
332
  try {
@@ -370,6 +348,8 @@ async function updateUserFiles() {
370
348
  }
371
349
  }
372
350
  else {
351
+ assert(isNonRunnableProcess);
352
+ assert(!viteDevServer);
373
353
  try {
374
354
  // We don't directly use import() because:
375
355
  // - Avoid Cloudflare Workers (without @cloudflare/vite-plugin) to try to bundle `import('virtual:id')`.
@@ -392,6 +372,7 @@ async function updateUserFiles() {
392
372
  return onError(err);
393
373
  virtualFileExportsGlobalEntry = virtualFileExportsGlobalEntry.default || virtualFileExportsGlobalEntry;
394
374
  if (getVikeConfigErrorBuild()) {
375
+ debugUpdate('=> aborted: build error');
395
376
  return { success: false };
396
377
  }
397
378
  try {
@@ -406,6 +387,45 @@ async function updateUserFiles() {
406
387
  if (hasError)
407
388
  return onError(err);
408
389
  return onSuccess();
390
+ function onSuccess() {
391
+ debugUpdate('=> onSuccess()');
392
+ if (globalObject.vikeConfigHasRuntimeError) {
393
+ assert(logRuntimeInfo); // always defined in dev
394
+ logRuntimeInfo(vikeConfigErrorRecoverMsg, null, 'error-resolve');
395
+ }
396
+ globalObject.vikeConfigHasRuntimeError = false;
397
+ setVikeConfigError({ errorRuntime: false });
398
+ globalObject.waitForUserFilesUpdateResolve.forEach((resolve) => resolve());
399
+ globalObject.waitForUserFilesUpdateResolve = [];
400
+ resolve();
401
+ return { success: true };
402
+ }
403
+ function onError(err) {
404
+ debugUpdate('=> onError()');
405
+ if (
406
+ // We must check whether the error was already logged to avoid printing it twice, e.g. when +onCreateGlobalContext.js has a syntax error
407
+ !hasAlreadyLogged(err)) {
408
+ logRuntimeError(err, null);
409
+ }
410
+ setVikeConfigError({ errorRuntime: { err } });
411
+ globalObject.vikeConfigHasRuntimeError = true;
412
+ return { success: false };
413
+ }
414
+ function isOutdated() {
415
+ const yes =
416
+ // There is a newer call — let the new call supersede the old one.
417
+ // We deliberately swallow the intermetidate state (including any potential error) — it's now outdated and has existed only for a very short period of time.
418
+ globalObject.waitForUserFilesUpdate !== promise ||
419
+ // Avoid race condition: abort if there is a new globalObject.viteDevServer (happens when vite.config.js is modified => Vite's dev server is fully reloaded).
420
+ viteDevServer !== globalObject.viteDevServer;
421
+ if (yes)
422
+ debugUpdate('=> aborted: isOutdated');
423
+ return yes;
424
+ }
425
+ function debugUpdate(...args) {
426
+ debug('updateUserFiles()', ...args);
427
+ debugFileChange('updateUserFiles()', ...args);
428
+ }
409
429
  }
410
430
  async function createGlobalContext(virtualFileExportsGlobalEntry) {
411
431
  debug('createGlobalContext()');
@@ -496,7 +516,7 @@ async function addGlobalContextAsync(globalContext) {
496
516
  else {
497
517
  assert(!isProcessSharedWithVite()); // process shared with Vite => globalObject.viteConfigRuntime should be set
498
518
  assert(!isProd()); // production => globalObject.buildInfo.viteConfigRuntime should be set
499
- assert(isNonRunnableDev());
519
+ assert(isNonRunnableDevProcess());
500
520
  const rpc = getViteRPC();
501
521
  viteConfigRuntime = await rpc.getViteConfigRuntimeRPC();
502
522
  }
@@ -528,17 +548,16 @@ function resolveBaseRuntime(viteConfigRuntime, config) {
528
548
  function isProcessSharedWithVite() {
529
549
  const yes = globalThis.__VIKE__IS_PROCESS_SHARED_WITH_VITE ?? false;
530
550
  if (yes)
531
- assert(!isNonRunnableDev());
551
+ assert(!isNonRunnableDevProcess());
532
552
  return yes;
533
553
  }
534
- function isRunnable(viteDevServer) {
554
+ function isRunnableDevServer(viteDevServer) {
555
+ assert(!isNonRunnableDevProcess()); // if `viteDevServer` exists => cannot be inside a non-runnable process
535
556
  const yes =
536
557
  // Vite 5
537
558
  !viteDevServer.environments ||
538
559
  // Vite 6 or above
539
560
  isRunnableDevEnvironment(viteDevServer.environments.ssr);
540
- if (yes)
541
- assert(!isNonRunnableDev());
542
561
  return yes;
543
562
  }
544
563
  function isProd() {
@@ -577,7 +596,7 @@ function isProdOptional() {
577
596
  // getGlobalContextAsync(isProduction)
578
597
  const no4 = globalObject.isProductionAccordingToUser === false;
579
598
  // @cloudflare/vite-plugin
580
- const no5 = isNonRunnableDev();
599
+ const no5 = isNonRunnableDevProcess();
581
600
  const no6 = globalThis.__VIKE__IS_DEV === true;
582
601
  const no = no1 || no2 || no3 || no4 || no5 || no6;
583
602
  const debug = { yes1, yes2, yes3, yes4, yes5, yes6, yes7, no1, no2, no3, no4, no5, no6 };
@@ -1,6 +1,13 @@
1
1
  export { execHookServer };
2
- import { execHook } from '../../../shared-server-client/hooks/execHook.js';
2
+ import { execHookDirect } from '../../../shared-server-client/hooks/execHook.js';
3
3
  import { preparePageContextForPublicUsageServer, } from './preparePageContextForPublicUsageServer.js';
4
+ import { getHookFromPageContextNew } from '../../../shared-server-client/hooks/getHook.js';
5
+ import { getFileSuffixes } from '../../../shared-server-node/getFileSuffixes.js';
4
6
  async function execHookServer(hookName, pageContext) {
5
- return await execHook(hookName, pageContext, preparePageContextForPublicUsageServer);
7
+ const allHooks = getHookFromPageContextNew(hookName, pageContext);
8
+ const hooks = !pageContext.isClientSideNavigation
9
+ ? allHooks
10
+ : // Don't execute `.ssr.js` hooks upon client-side navigation
11
+ allHooks.filter((hook) => !getFileSuffixes(hook.hookFilePath).includes('ssr'));
12
+ return await execHookDirect(hooks, pageContext, preparePageContextForPublicUsageServer);
6
13
  }
@@ -219,17 +219,14 @@ function logHttpRequest(urlOriginal, pageContextInit, requestId) {
219
219
  const pageContext_logRuntime = getPageContext_logRuntimeEarly(pageContextInit, requestId);
220
220
  logRuntimeInfo?.(getRequestInfoMessage(urlOriginal), pageContext_logRuntime, 'info');
221
221
  }
222
- /*
223
- const arrowRight = pc.dim('')
224
- const arrowLeft = pc.dim('')
225
- */
226
- /*
222
+ /* Alternative icons:
223
+ const arrowRight = pc.dim('»')
224
+ const arrowLeft = pc.dim('«')
227
225
  const arrowRight = pc.dim('>>')
228
226
  const arrowLeft = pc.dim('<<')
229
- /*/
230
- const arrowRight = pc.dim('»');
231
- const arrowLeft = pc.dim('«');
232
- //*/
227
+ */
228
+ const arrowRight = pc.dim('');
229
+ const arrowLeft = pc.dim('');
233
230
  function getRequestInfoMessage(urlOriginal) {
234
231
  return `HTTP request ${arrowRight} ${prettyUrl(urlOriginal)}`;
235
232
  }
@@ -60,6 +60,6 @@ export * from '../utils/changeEnumerable.js';
60
60
  export * from '../utils/getViteRPC.js';
61
61
  export * from '../utils/isRunnableDevEnvironment.js';
62
62
  export * from '../utils/assertIsNotBrowser.js';
63
- export * from '../utils/isNonRunnableDev.js';
63
+ export * from '../utils/isNonRunnableDevProcess.js';
64
64
  export * from '../utils/catchInfiniteLoop.js';
65
65
  export * from '../utils/getBetterError.js';
@@ -64,6 +64,6 @@ export * from '../utils/changeEnumerable.js';
64
64
  export * from '../utils/getViteRPC.js';
65
65
  export * from '../utils/isRunnableDevEnvironment.js';
66
66
  export * from '../utils/assertIsNotBrowser.js';
67
- export * from '../utils/isNonRunnableDev.js';
67
+ export * from '../utils/isNonRunnableDevProcess.js';
68
68
  export * from '../utils/catchInfiniteLoop.js';
69
69
  export * from '../utils/getBetterError.js';
@@ -0,0 +1,2 @@
1
+ export { assertVirtualFileExports };
2
+ declare function assertVirtualFileExports<ModuleExports>(moduleExports: ModuleExports, test: (moduleExports: ModuleExports) => boolean, moduleId?: string): void;
@@ -0,0 +1,16 @@
1
+ export { assertVirtualFileExports };
2
+ import { assert } from './utils.js';
3
+ function assertVirtualFileExports(moduleExports, test, moduleId) {
4
+ if (!moduleExports || !test(moduleExports)) {
5
+ /* https://github.com/vikejs/vike/issues/2903#issuecomment-3642285811
6
+ throw getProjectError('@cloudflare/vite-plugin error https://github.com/vikejs/vike/issues/2903#issuecomment-3642285811')
7
+ /*/
8
+ assert(false, { moduleExports, moduleExportsKeys: getKeys(moduleExports), moduleId });
9
+ //*/
10
+ }
11
+ }
12
+ function getKeys(obj) {
13
+ if (obj === undefined)
14
+ return null;
15
+ return [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj), ...Object.keys(obj)];
16
+ }
@@ -24,50 +24,54 @@ addGlobalContextTmp, addGlobalContextAsync) {
24
24
  assert(globalObject.globalContext);
25
25
  await previousCreateGlobalContextPromise;
26
26
  }
27
- const globalContext = createGlobalContextBase(virtualFileExportsGlobalEntry);
28
- let isNewGlobalContext;
29
- if (!globalObject.globalContext) {
30
- // We set globalObject.globalContext early and before any async operations, so that getGlobalContextSync() can be used early.
31
- // - Required by vike-vercel
32
- globalObject.globalContext = globalContext;
33
- isNewGlobalContext = false;
34
- }
35
- else {
36
- isNewGlobalContext = true;
37
- }
38
- if (addGlobalContext &&
39
- // TO-DO/next-major-release: remove
40
- globalContext._pageConfigs.length > 0) {
41
- const globalContextAdded = addGlobalContext?.(globalContext);
42
- objectAssign(globalContext, globalContextAdded);
43
- }
44
- else {
45
- const globalContextAdded = await addGlobalContextTmp?.(globalContext);
46
- objectAssign(globalContext, globalContextAdded);
47
- }
48
- {
49
- const globalContextAddedAsync = await addGlobalContextAsync?.(globalContext);
50
- objectAssign(globalContext, globalContextAddedAsync);
51
- }
52
- const onCreateGlobalContextHooks = getHookFromPageConfigGlobalCumulative(globalContext._pageConfigGlobal, 'onCreateGlobalContext');
53
- let hooksCalled = false;
54
- if (!hooksAreEqual(globalObject.onCreateGlobalContextHooks ?? [], onCreateGlobalContextHooks)) {
55
- globalObject.onCreateGlobalContextHooks = onCreateGlobalContextHooks;
56
- await execHookGlobal('onCreateGlobalContext', globalContext._pageConfigGlobal, null, globalContext, prepareGlobalContextForPublicUsage);
57
- hooksCalled = true;
58
- }
59
- if (isNewGlobalContext) {
60
- // Singleton: ensure all `globalContext` user-land references are preserved & updated.
61
- if (hooksCalled) {
62
- objectReplace(globalObject.globalContext, globalContext);
27
+ try {
28
+ const globalContext = createGlobalContextBase(virtualFileExportsGlobalEntry);
29
+ let isNewGlobalContext;
30
+ if (!globalObject.globalContext) {
31
+ // We set globalObject.globalContext early and before any async operations, so that getGlobalContextSync() can be used early.
32
+ // - Required by vike-vercel
33
+ globalObject.globalContext = globalContext;
34
+ isNewGlobalContext = false;
63
35
  }
64
36
  else {
65
- // We don't use objectReplace() in order to keep user-land properties.
66
- objectAssign(globalObject.globalContext, globalContext, true);
37
+ isNewGlobalContext = true;
38
+ }
39
+ if (addGlobalContext &&
40
+ // TO-DO/next-major-release: remove
41
+ globalContext._pageConfigs.length > 0) {
42
+ const globalContextAdded = addGlobalContext?.(globalContext);
43
+ objectAssign(globalContext, globalContextAdded);
67
44
  }
45
+ else {
46
+ const globalContextAdded = await addGlobalContextTmp?.(globalContext);
47
+ objectAssign(globalContext, globalContextAdded);
48
+ }
49
+ {
50
+ const globalContextAddedAsync = await addGlobalContextAsync?.(globalContext);
51
+ objectAssign(globalContext, globalContextAddedAsync);
52
+ }
53
+ const onCreateGlobalContextHooks = getHookFromPageConfigGlobalCumulative(globalContext._pageConfigGlobal, 'onCreateGlobalContext');
54
+ let hooksCalled = false;
55
+ if (!hooksAreEqual(globalObject.onCreateGlobalContextHooks ?? [], onCreateGlobalContextHooks)) {
56
+ globalObject.onCreateGlobalContextHooks = onCreateGlobalContextHooks;
57
+ await execHookGlobal('onCreateGlobalContext', globalContext._pageConfigGlobal, null, globalContext, prepareGlobalContextForPublicUsage);
58
+ hooksCalled = true;
59
+ }
60
+ if (isNewGlobalContext) {
61
+ // Singleton: ensure all `globalContext` user-land references are preserved & updated.
62
+ if (hooksCalled) {
63
+ objectReplace(globalObject.globalContext, globalContext);
64
+ }
65
+ else {
66
+ // We don't use objectReplace() in order to keep user-land properties.
67
+ objectAssign(globalObject.globalContext, globalContext, true);
68
+ }
69
+ }
70
+ return globalObject.globalContext;
71
+ }
72
+ finally {
73
+ resolve();
68
74
  }
69
- resolve();
70
- return globalObject.globalContext;
71
75
  }
72
76
  function createGlobalContextBase(virtualFileExportsGlobalEntry) {
73
77
  const { pageFilesAll, pageConfigs, pageConfigGlobal } = parseVirtualFileExportsGlobalEntry(virtualFileExportsGlobalEntry);
@@ -5,7 +5,9 @@ import { assertExportValues } from './assert_exports_old_design.js';
5
5
  import { getPageFileObject } from './getPageFileObject.js';
6
6
  import { fileTypes } from './fileTypes.js';
7
7
  import { parsePageConfigsSerialized } from '../page-configs/serialize/parsePageConfigsSerialized.js';
8
+ import { assertVirtualFileExports } from '../assertVirtualFileExports.js';
8
9
  function parseVirtualFileExportsGlobalEntry(virtualFileExportsGlobalEntry) {
10
+ assertVirtualFileExports(virtualFileExportsGlobalEntry, (moduleExports) => 'pageFilesLazy' in moduleExports);
9
11
  assert(hasProp(virtualFileExportsGlobalEntry, 'pageFilesLazy', 'object'));
10
12
  assert(hasProp(virtualFileExportsGlobalEntry, 'pageFilesEager', 'object'));
11
13
  assert(hasProp(virtualFileExportsGlobalEntry, 'pageFilesExportNamesLazy', 'object'));
@@ -1,6 +1,7 @@
1
1
  export { loadAndParseVirtualFilePageEntry };
2
- import { assert, objectAssign } from '../utils.js';
2
+ import { objectAssign } from '../utils.js';
3
3
  import { parseConfigValuesSerialized } from './serialize/parsePageConfigsSerialized.js';
4
+ import { assertVirtualFileExports } from '../assertVirtualFileExports.js';
4
5
  async function loadAndParseVirtualFilePageEntry(pageConfig, isDev) {
5
6
  if ('isPageEntryLoaded' in pageConfig &&
6
7
  // We don't need to cache in dev, since Vite already caches the virtual module
@@ -8,10 +9,13 @@ async function loadAndParseVirtualFilePageEntry(pageConfig, isDev) {
8
9
  return pageConfig;
9
10
  }
10
11
  const { moduleId, moduleExportsPromise } = pageConfig.loadVirtualFilePageEntry();
11
- const virtualFileExportsPageEntry = await moduleExportsPromise;
12
- // `configValuesLoaded` is sometimes `undefined` https://github.com/vikejs/vike/discussions/2092
13
- if (!virtualFileExportsPageEntry)
14
- assert(false, { moduleExportsPromise, virtualFileExportsPageEntry, moduleId });
12
+ const moduleExports = await moduleExportsPromise;
13
+ /* `moduleExports` is sometimes `undefined` https://github.com/vikejs/vike/discussions/2092
14
+ assert(moduleExports)
15
+ //*/
16
+ // Catch @cloudflare/vite-plugin bug
17
+ assertVirtualFileExports(moduleExports, () => 'configValuesSerialized' in moduleExports, moduleId);
18
+ const virtualFileExportsPageEntry = moduleExports;
15
19
  const configValues = parseVirtualFileExportsPageEntry(virtualFileExportsPageEntry);
16
20
  Object.assign(pageConfig.configValues, configValues);
17
21
  objectAssign(pageConfig, { isPageEntryLoaded: true });
@@ -0,0 +1,6 @@
1
+ export { getFileSuffixes };
2
+ export { suffixesAssertFileEnv };
3
+ declare const suffixesAssertFileEnv: readonly ["server", "client", "ssr"];
4
+ declare const suffixes: readonly ["server", "client", "ssr", "shared", "clear", "default"];
5
+ type Suffix = (typeof suffixes)[number];
6
+ declare function getFileSuffixes(fileName: string): Suffix[];
@@ -0,0 +1,22 @@
1
+ export { getFileSuffixes };
2
+ export { suffixesAssertFileEnv };
3
+ const suffixesAssertFileEnv = [
4
+ // .server.js
5
+ 'server',
6
+ // .client.js
7
+ 'client',
8
+ // .ssr.js
9
+ 'ssr',
10
+ ];
11
+ const suffixes = [
12
+ ...suffixesAssertFileEnv,
13
+ // .shared.js
14
+ 'shared',
15
+ // .clear.js
16
+ 'clear',
17
+ // .default.js
18
+ 'default',
19
+ ];
20
+ function getFileSuffixes(fileName) {
21
+ return suffixes.filter((suffix) => fileName.includes(`.${suffix}.`));
22
+ }
@@ -1,6 +1,15 @@
1
1
  export { getVikeConfigError };
2
2
  export { getVikeConfigErrorBuild };
3
3
  export { setVikeConfigError };
4
+ export { debugFileChange };
5
+ declare const debugFileChange: ((...msgs: unknown[]) => void) & {
6
+ options: (optionsLocal: {
7
+ serialization?: {
8
+ emptyArray?: string;
9
+ };
10
+ }) => (...msgs: unknown[]) => void;
11
+ isActivated: boolean;
12
+ };
4
13
  type VikeConfigHasError = false | {
5
14
  err: unknown;
6
15
  };
@@ -1,12 +1,15 @@
1
1
  export { getVikeConfigError };
2
2
  export { getVikeConfigErrorBuild };
3
3
  export { setVikeConfigError };
4
- import { getGlobalObject } from './utils.js';
4
+ export { debugFileChange };
5
+ import { getGlobalObject, createDebug } from './utils.js';
5
6
  const globalObject = getGlobalObject('server/shared/getVikeConfigError.ts', {
6
7
  errorRuntime: false,
7
8
  errorBuild: false,
8
9
  });
10
+ const debugFileChange = createDebug('vike:file-change');
9
11
  function setVikeConfigError(val) {
12
+ debugFileChange('setVikeConfigError()', val);
10
13
  if ('errorRuntime' in val)
11
14
  globalObject.errorRuntime = val.errorRuntime;
12
15
  if ('errorBuild' in val)
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.247-commit-87e5f2f";
1
+ export declare const PROJECT_VERSION: "0.4.247-commit-1250e38";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.247-commit-87e5f2f';
2
+ export const PROJECT_VERSION = '0.4.247-commit-1250e38';
@@ -12,7 +12,7 @@ import { assert, assertUsage, assertWarning } from './assert.js';
12
12
  import { assertIsNotBrowser } from './assertIsNotBrowser.js';
13
13
  import { createDebug } from './debug.js';
14
14
  import { getGlobalObject } from './getGlobalObject.js';
15
- import { isNonRunnableDev } from './isNonRunnableDev.js';
15
+ import { isNonRunnableDevProcess } from './isNonRunnableDevProcess.js';
16
16
  import { isVitest } from './isVitest.js';
17
17
  import pc from '@brillout/picocolors';
18
18
  assertIsNotBrowser();
@@ -32,9 +32,9 @@ function onSetupRuntime() {
32
32
  assertNodeEnvIsNotUndefinedString();
33
33
  if (!setup.viteDevServer && setup.isViteDev === undefined) {
34
34
  // TO-DO/eventually: make it assertUsage() again once https://github.com/vikejs/vike/issues/1528 is implemented.
35
- assertWarning(!isNodeEnvDev() || isNonRunnableDev(), `The ${getEnvDescription()}, which is contradictory because the environment seems to be a production environment (Vite isn't loaded), see ${pc.underline('https://vike.dev/NODE_ENV')} and ${pc.underline('https://vike.dev/warning/setup')}`, { onlyOnce: true });
35
+ assertWarning(!isNodeEnvDev() || isNonRunnableDevProcess(), `The ${getEnvDescription()}, which is contradictory because the environment seems to be a production environment (Vite isn't loaded), see ${pc.underline('https://vike.dev/NODE_ENV')} and ${pc.underline('https://vike.dev/warning/setup')}`, { onlyOnce: true });
36
36
  assertUsage(!setup.vikeVitePlugin, `Vike's Vite plugin (the ${pc.cyan('vike/plugin')} module) shouldn't be loaded in production, see ${pc.underline('https://vike.dev/warning/setup')}`);
37
- // This assert() one of the main goal of this file: it ensures assertIsNotProductionRuntime()
37
+ // This assert() one of the main goal of this file: it implements assertIsNotProductionRuntime()
38
38
  assert(!setup.shouldNotBeProduction);
39
39
  }
40
40
  else {
@@ -2,7 +2,7 @@ export { createDebug };
2
2
  export { isDebug };
3
3
  export { isDebugError };
4
4
  export { debug };
5
- declare const flags: ["vike", "vike:crawl", "vike:error", "vike:esbuild-resolve", "vike:pluginExtractAssets", "vike:pluginExtractExportNames", "vike:glob", "vike:globalContext", "vike:log", "vike:optimizeDeps", "vike:outDir", "vike:pageFiles", "vike:pointer-imports", "vike:requireResolve", "vike:routing", "vike:setup", "vike:stream", "vike:virtualFiles", "vike:vite-rpc"];
5
+ declare const flags: ["vike", "vike:crawl", "vike:file-change", "vike:error", "vike:esbuild-resolve", "vike:pluginExtractAssets", "vike:pluginExtractExportNames", "vike:glob", "vike:globalContext", "vike:log", "vike:optimizeDeps", "vike:outDir", "vike:pageFiles", "vike:pointer-imports", "vike:requireResolve", "vike:routing", "vike:setup", "vike:stream", "vike:virtualFiles", "vike:vite-rpc"];
6
6
  type Flag = (typeof flags)[number];
7
7
  type Options = {
8
8
  serialization?: {
@@ -12,6 +12,7 @@ import { isObject } from './isObject.js';
12
12
  const flags = [
13
13
  'vike',
14
14
  'vike:crawl',
15
+ 'vike:file-change',
15
16
  'vike:error',
16
17
  'vike:esbuild-resolve',
17
18
  'vike:pluginExtractAssets',
@@ -1,5 +1,8 @@
1
1
  export { getBetterError };
2
2
  // TO-DO/maybe: make it a library `@brillout/better-error`
3
+ // Copies:
4
+ // - https://github.com/brillout/react-streaming/blob/b8565c1257c63a665bda31b9be42112e458859d1/src/utils/getBetterError.ts
5
+ // - https://github.com/vikejs/vike-react/blob/5477461e67592e24d2aa38a552703b9e76a01d2a/packages/vike-react/src/utils/getBetterErrorLight.ts
3
6
  import { isObject } from './isObject.js';
4
7
  import { assertIsNotBrowser } from './assertIsNotBrowser.js';
5
8
  import { objectAssign } from './objectAssign.js';
@@ -0,0 +1,2 @@
1
+ export { isNonRunnableDevProcess };
2
+ declare function isNonRunnableDevProcess(): boolean;
@@ -1,8 +1,8 @@
1
- export { isNonRunnableDev };
1
+ export { isNonRunnableDevProcess };
2
2
  import { assert } from './assert.js';
3
3
  import { assertIsNotBrowser } from './assertIsNotBrowser.js';
4
4
  assertIsNotBrowser();
5
- function isNonRunnableDev() {
5
+ function isNonRunnableDevProcess() {
6
6
  if (globalThis.__VIKE__IS_NON_RUNNABLE_DEV === undefined)
7
7
  return false;
8
8
  assert(globalThis.__VIKE__IS_NON_RUNNABLE_DEV === true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.247-commit-87e5f2f",
3
+ "version": "0.4.247-commit-1250e38",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -244,13 +244,13 @@
244
244
  "./universal-middleware.js"
245
245
  ],
246
246
  "devDependencies": {
247
- "@brillout/release-me": "^0.4.2",
247
+ "@brillout/release-me": "^0.4.9",
248
248
  "@types/estree": "^1.0.5",
249
249
  "@types/node": "^20.10.5",
250
250
  "@types/picomatch": "^3.0.2",
251
251
  "@types/semver": "^7.5.8",
252
252
  "@types/source-map-support": "^0.5.10",
253
- "react-streaming": "^0.4.13",
253
+ "react-streaming": "^0.4.14",
254
254
  "rimraf": "^5.0.5",
255
255
  "typescript": "^5.9.3",
256
256
  "vite": "^7.2.6"
@@ -1,3 +0,0 @@
1
- export { determineOptimizeDeps };
2
- import type { ResolvedConfig } from 'vite';
3
- declare function determineOptimizeDeps(config: ResolvedConfig): Promise<void>;
@@ -1,3 +0,0 @@
1
- export { pluginFileEnv };
2
- import type { Plugin } from 'vite';
3
- declare function pluginFileEnv(): Plugin[];
@@ -1,2 +0,0 @@
1
- export { isNonRunnableDev };
2
- declare function isNonRunnableDev(): boolean;