vike 0.4.240 → 0.4.241-commit-206146b

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 (74) hide show
  1. package/dist/esm/client/runtime-client-routing/getPageContextFromHooks.d.ts +1 -1
  2. package/dist/esm/client/runtime-client-routing/getPageContextFromHooks.js +1 -1
  3. package/dist/esm/client/runtime-client-routing/logErrorClient.d.ts +2 -0
  4. package/dist/esm/client/runtime-client-routing/logErrorClient.js +11 -0
  5. package/dist/esm/client/runtime-client-routing/renderPageClientSide.js +95 -84
  6. package/dist/esm/client/runtime-client-routing/utils.d.ts +0 -1
  7. package/dist/esm/client/runtime-client-routing/utils.js +0 -1
  8. package/dist/esm/node/cli/parseCli.js +10 -6
  9. package/dist/esm/node/prerender/runPrerender.js +2 -1
  10. package/dist/esm/node/runtime/globalContext.d.ts +92 -0
  11. package/dist/esm/node/runtime/globalContext.js +12 -3
  12. package/dist/esm/node/runtime/logErrorServer.d.ts +2 -0
  13. package/dist/esm/node/runtime/logErrorServer.js +17 -0
  14. package/dist/esm/node/runtime/renderPage/execHookOnError.d.ts +2 -0
  15. package/dist/esm/node/runtime/renderPage/execHookOnError.js +26 -0
  16. package/dist/esm/node/runtime/renderPage/execHookServer.d.ts +1 -1
  17. package/dist/esm/node/runtime/renderPage/loggerProd.js +3 -5
  18. package/dist/esm/node/runtime/renderPage.js +8 -7
  19. package/dist/esm/node/vite/index.js +6 -6
  20. package/dist/esm/node/vite/onLoad.js +3 -8
  21. package/dist/esm/node/vite/plugins/build/handleAssetsManifest.js +0 -1
  22. package/dist/esm/node/vite/plugins/build/pluginDistFileNames.js +2 -2
  23. package/dist/esm/node/vite/plugins/pluginCommon.js +13 -2
  24. package/dist/esm/node/vite/plugins/pluginFileEnv.js +9 -6
  25. package/dist/esm/node/vite/plugins/pluginReplaceConstantsEnvVars.d.ts +3 -0
  26. package/dist/esm/node/vite/plugins/pluginReplaceConstantsEnvVars.js +129 -0
  27. package/dist/esm/node/vite/plugins/pluginReplaceConstantsGlobalThis.d.ts +10 -0
  28. package/dist/esm/node/vite/plugins/pluginReplaceConstantsGlobalThis.js +77 -0
  29. package/dist/esm/node/vite/plugins/pluginReplaceConstantsPageContext.d.ts +3 -0
  30. package/dist/esm/node/vite/plugins/{pluginReplaceIsClientSide.js → pluginReplaceConstantsPageContext.js} +5 -3
  31. package/dist/esm/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.js +7 -1
  32. package/dist/esm/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntryWithOldDesign.js +3 -0
  33. package/dist/esm/node/vite/plugins/pluginVirtualFiles.js +2 -2
  34. package/dist/esm/node/vite/shared/getFilePath.d.ts +4 -6
  35. package/dist/esm/node/vite/shared/getFilePath.js +6 -11
  36. package/dist/esm/node/vite/shared/isViteServerSide.d.ts +6 -3
  37. package/dist/esm/node/vite/shared/isViteServerSide.js +13 -4
  38. package/dist/esm/node/vite/shared/loggerNotProd/errorWithCodeSnippet.js +2 -2
  39. package/dist/esm/node/vite/shared/loggerNotProd/log.js +8 -2
  40. package/dist/esm/node/vite/shared/loggerNotProd.d.ts +1 -1
  41. package/dist/esm/node/vite/shared/loggerNotProd.js +11 -11
  42. package/dist/esm/node/vite/shared/loggerVite.js +4 -2
  43. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +12 -2
  44. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/transpileAndExecuteFile.js +1 -6
  45. package/dist/esm/shared/createGlobalContextShared.d.ts +2 -1
  46. package/dist/esm/shared/createGlobalContextShared.js +1 -1
  47. package/dist/esm/shared/hooks/execHook.d.ts +1 -1
  48. package/dist/esm/shared/hooks/getHook.d.ts +5 -4
  49. package/dist/esm/shared/route/abort.d.ts +1 -0
  50. package/dist/esm/shared/route/abort.js +12 -4
  51. package/dist/esm/shared/route/index.js +13 -4
  52. package/dist/esm/shared/route/utils.d.ts +1 -0
  53. package/dist/esm/shared/route/utils.js +1 -0
  54. package/dist/esm/types/Config.d.ts +14 -3
  55. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  56. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  57. package/dist/esm/utils/assert.js +1 -0
  58. package/dist/esm/utils/assertNodeVersion.js +1 -1
  59. package/dist/esm/utils/assertViteVersion.d.ts +2 -0
  60. package/dist/esm/utils/assertViteVersion.js +11 -0
  61. package/dist/esm/utils/debug.d.ts +5 -3
  62. package/dist/esm/utils/debug.js +20 -16
  63. package/dist/esm/utils/getGlobalObject.d.ts +5 -1
  64. package/dist/esm/utils/getGlobalObject.js +5 -1
  65. package/dist/esm/utils/isVikeReactApp.js +2 -1
  66. package/dist/esm/utils/requireResolve.js +1 -1
  67. package/package.json +3 -3
  68. package/dist/esm/node/vite/plugins/pluginEnvVars.d.ts +0 -3
  69. package/dist/esm/node/vite/plugins/pluginEnvVars.js +0 -110
  70. package/dist/esm/node/vite/plugins/pluginReplaceGlobalThisConstants.d.ts +0 -9
  71. package/dist/esm/node/vite/plugins/pluginReplaceGlobalThisConstants.js +0 -45
  72. package/dist/esm/node/vite/plugins/pluginReplaceIsClientSide.d.ts +0 -3
  73. package/dist/esm/shared/route/debug.d.ts +0 -6
  74. package/dist/esm/shared/route/debug.js +0 -21
@@ -16,12 +16,12 @@ import { pluginExtractExportNames } from './plugins/pluginExtractExportNames.js'
16
16
  import { pluginSetGlobalContext } from './plugins/pluginSetGlobalContext.js';
17
17
  import { pluginCommon } from './plugins/pluginCommon.js';
18
18
  import { pluginBaseUrls } from './plugins/pluginBaseUrls.js';
19
- import { pluginEnvVars } from './plugins/pluginEnvVars.js';
19
+ import { pluginReplaceConstantsEnvVars } from './plugins/pluginReplaceConstantsEnvVars.js';
20
20
  import { pluginFileEnv } from './plugins/pluginFileEnv.js';
21
21
  import { pluginWorkaroundCssModuleHmr } from './plugins/pluginWorkaroundCssModuleHmr.js';
22
22
  import { pluginWorkaroundVite6HmrRegression } from './plugins/pluginWorkaroundVite6HmrRegression.js';
23
- import { pluginReplaceIsClientSide } from './plugins/pluginReplaceIsClientSide.js';
24
- import { pluginReplaceGlobalThisConstants } from './plugins/pluginReplaceGlobalThisConstants.js';
23
+ import { pluginReplaceConstantsPageContext } from './plugins/pluginReplaceConstantsPageContext.js';
24
+ import { pluginReplaceConstantsGlobalThis } from './plugins/pluginReplaceConstantsGlobalThis.js';
25
25
  import { pluginViteRPC } from './plugins/non-runnable-dev/pluginViteRPC.js';
26
26
  import { pluginBuildApp } from './plugins/build/pluginBuildApp.js';
27
27
  import { pluginDistPackageJsonFile } from './plugins/build/pluginDistPackageJsonFile.js';
@@ -46,12 +46,12 @@ function plugin(vikeVitePluginOptions = {}) {
46
46
  ...pluginExtractExportNames(),
47
47
  ...pluginSetGlobalContext(),
48
48
  ...pluginBaseUrls(),
49
- ...pluginEnvVars(),
49
+ ...pluginReplaceConstantsEnvVars(),
50
50
  ...pluginFileEnv(),
51
51
  ...pluginWorkaroundCssModuleHmr(),
52
52
  ...pluginWorkaroundVite6HmrRegression(),
53
- ...pluginReplaceIsClientSide(),
54
- ...pluginReplaceGlobalThisConstants(),
53
+ ...pluginReplaceConstantsPageContext(),
54
+ ...pluginReplaceConstantsGlobalThis(),
55
55
  ...pluginNonRunnabeDev(),
56
56
  ];
57
57
  Object.assign(plugins, { _vikeVitePluginOptions: vikeVitePluginOptions });
@@ -2,18 +2,13 @@ export { onLoad };
2
2
  import { assertIsNotBrowser } from '../../utils/assertIsNotBrowser.js';
3
3
  import { assertIsNotProductionRuntime, markSetup_vikeVitePlugin } from '../../utils/assertSetup.js';
4
4
  import { assertNodeVersion } from '../../utils/assertNodeVersion.js';
5
- import { assertVersion } from '../../utils/assertVersion.js';
6
- import { version } from 'vite';
5
+ import { version as viteVersion } from 'vite';
6
+ import { assertViteVersion } from '../../utils/assertViteVersion.js';
7
7
  function onLoad() {
8
8
  markSetup_vikeVitePlugin();
9
9
  assertIsNotBrowser();
10
10
  assertNodeVersion();
11
- // package.json#peerDependencies isn't enough as users often ignore it
12
- // This assertion isn't reliable: the user may still use a Vite version older than 6.0.0 — see https://github.com/vitejs/vite/pull/19355
13
- // TO-DO/eventually: let's also use this.meta.viteVersion
14
- // - https://github.com/vitejs/vite/pull/20088
15
- // - https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#700-2025-06-24
16
- assertVersion('Vite', version, ['6.3.0']);
11
+ assertViteVersion(viteVersion);
17
12
  // Ensure we don't bloat the server runtime with heavy dependencies such Vite and esbuild
18
13
  assertIsNotProductionRuntime();
19
14
  }
@@ -310,7 +310,6 @@ async function handleAssetsManifest_getBuildConfig() {
310
310
  async function handleAssetsManifest(config, viteEnv, options, bundle) {
311
311
  const isSsrEnv = isViteServerSide_onlySsrEnv(config, viteEnv);
312
312
  if (isSsrEnv) {
313
- assert(!globalObject.assetsJsonFilePath);
314
313
  const outDirs = getOutDirs(config, viteEnv);
315
314
  globalObject.assetsJsonFilePath = path.posix.join(outDirs.outDirRoot, 'assets.json');
316
315
  await writeAssetsManifestFile(globalObject.assetsJsonFilePath, config);
@@ -6,7 +6,7 @@ import { assertPosixPath, assert, assertUsage, isArray, isCallable } from '../..
6
6
  import path from 'node:path';
7
7
  import crypto from 'node:crypto';
8
8
  import { getAssetsDir } from '../../shared/getAssetsDir.js';
9
- import { assertModuleId, getModuleFilePathAbsolute } from '../../shared/getFilePath.js';
9
+ import { assertModuleId, getFilePathToShowToUserModule } from '../../shared/getFilePath.js';
10
10
  function pluginDistFileNames() {
11
11
  return [
12
12
  {
@@ -63,7 +63,7 @@ function pluginDistFileNames() {
63
63
  name = isNodeModules[1];
64
64
  }
65
65
  else {
66
- const filePath = getModuleFilePathAbsolute(id, config);
66
+ const filePath = getFilePathToShowToUserModule(id, config);
67
67
  name = filePath;
68
68
  name = name.split('.').slice(0, -1).join('.'); // remove file extension
69
69
  name = name.split('/').filter(Boolean).join('_');
@@ -91,6 +91,11 @@ function pluginCommon(vikeVitePluginOptions) {
91
91
  // Set `--host` for Docker/Podman
92
92
  setDefault('host', true, configFromUser, configFromVike);
93
93
  }
94
+ // https://vike.dev/force
95
+ if (vikeConfig.config.force !== undefined && configFromUser.optimizeDeps?.force === undefined) {
96
+ configFromVike.optimizeDeps ?? (configFromVike.optimizeDeps = {});
97
+ configFromVike.optimizeDeps.force = vikeConfig.config.force;
98
+ }
94
99
  return configFromVike;
95
100
  },
96
101
  },
@@ -131,10 +136,16 @@ function assertVikeCliOrApi(config) {
131
136
  assert(!isVitest());
132
137
  return;
133
138
  }
139
+ /* This warning is always shown: Vitest loads Vite *before* any Vike JavaScript API can be invoked.
134
140
  if (isVitest()) {
135
- assertWarning(false, `Unexpected Vitest setup: you seem to be using Vitest together with Vike's Vite plugin but without using Vike's JavaScript API which is unexpected, see ${pc.underline('https://vike.dev/vitest')}`, { onlyOnce: true });
136
- return;
141
+ assertWarning(
142
+ false,
143
+ `Unexpected Vitest setup: you seem to be using Vitest together with Vike's Vite plugin but without using Vike's JavaScript API which is unexpected, see ${pc.underline('https://vike.dev/vitest')}`,
144
+ { onlyOnce: true },
145
+ )
146
+ return
137
147
  }
148
+ */
138
149
  if (config.server.middlewareMode) {
139
150
  assertWarning(false, `${pc.cyan('vite.createServer()')} is deprecated ${pc.underline('https://vike.dev/migration/cli#api')}`, {
140
151
  onlyOnce: true,
@@ -3,7 +3,7 @@ import { assert, assertUsage, assertWarning, capitalizeFirstLetter, isFilePathAb
3
3
  import { extractAssetsRE } from './pluginExtractAssets.js';
4
4
  import { extractExportNamesRE } from './pluginExtractExportNames.js';
5
5
  import pc from '@brillout/picocolors';
6
- import { getModuleFilePathAbsolute } from '../shared/getFilePath.js';
6
+ import { getFilePathToShowToUserModule } from '../shared/getFilePath.js';
7
7
  import { getExportNames } from '../shared/parseEsModule.js';
8
8
  import { normalizeId } from '../shared/normalizeId.js';
9
9
  import { isV1Design } from '../shared/resolveVikeConfigInternal.js';
@@ -42,8 +42,10 @@ function pluginFileEnv() {
42
42
  if (id.endsWith('?direct'))
43
43
  id = id.slice(0, -1 * '?direct'.length);
44
44
  const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
45
- assert(moduleInfo);
46
- const importers = Array.from(moduleInfo.importers)
45
+ /* It can fail, no clue why — https://github.com/vikejs/vike/issues/2740
46
+ assert(moduleInfo, { moduleId })
47
+ */
48
+ const importers = (!moduleInfo ? [] : Array.from(moduleInfo.importers))
47
49
  .map((m) => m.id)
48
50
  .filter((id) => id !== null);
49
51
  assertFileEnv(id, isViteServerSide_extraSafe(config, this.environment, options), importers,
@@ -122,7 +124,7 @@ function pluginFileEnv() {
122
124
  const envActual = isServerSide ? 'server' : 'client';
123
125
  const envExpect = isServerSide ? 'client' : 'server';
124
126
  let errMsg;
125
- let modulePathPretty = getModuleFilePathAbsolute(modulePath, config);
127
+ let modulePathPretty = getFilePathToShowToUserModule(modulePath, config);
126
128
  if (!noColor) {
127
129
  const suffix = getSuffix(envExpect);
128
130
  modulePathPretty = modulePathPretty.replaceAll(suffix, pc.bold(suffix));
@@ -133,13 +135,14 @@ function pluginFileEnv() {
133
135
  .filter((importer) =>
134
136
  // Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
135
137
  isFilePathAbsolute(importer))
136
- .map((importer) => getModuleFilePathAbsolute(importer, config));
138
+ .map((importer) => getFilePathToShowToUserModule(importer, config))
139
+ .map((importPath) => pc.cyan(importPath));
137
140
  if (importPaths.length > 0) {
138
141
  errMsg += ` by ${joinEnglish(importPaths, 'and')}`;
139
142
  }
140
143
  }
141
144
  if (onlyWarn) {
142
- errMsg += ' and, therefore, Vike will prevent building your app for production.';
145
+ errMsg += ". This is potentially a security issue and Vike won't allow you to build your app for production.";
143
146
  }
144
147
  return errMsg;
145
148
  }
@@ -0,0 +1,3 @@
1
+ export { pluginReplaceConstantsEnvVars };
2
+ import type { Plugin } from 'vite';
3
+ declare function pluginReplaceConstantsEnvVars(): Plugin[];
@@ -0,0 +1,129 @@
1
+ export { pluginReplaceConstantsEnvVars };
2
+ import { loadEnv } from 'vite';
3
+ import { assert, assertPosixPath, assertUsage, assertWarning, escapeRegex, isArray, isNotNullish, lowerFirst, } from '../utils.js';
4
+ import { getFilePathToShowToUserModule } from '../shared/getFilePath.js';
5
+ import { normalizeId } from '../shared/normalizeId.js';
6
+ import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
7
+ import { getMagicString } from '../shared/getMagicString.js';
8
+ const PUBLIC_ENV_PREFIX = 'PUBLIC_ENV__';
9
+ const PUBLIC_ENV_ALLOWLIST = [
10
+ // https://github.com/vikejs/vike/issues/1724
11
+ 'STORYBOOK',
12
+ ];
13
+ // TO-DO/eventually:
14
+ // - Make import.meta.env work inside +config.js
15
+ // - For it to work, we'll probably need the user to define the settings (e.g. `envDir`) for loadEnv() inside vike.config.js instead of vite.config.js
16
+ // - Or stop using Vite's `mode` implementation and have Vike implement its own `mode` feature? (So that the only dependencies are `$ vike build --mode staging` and `$ MODE=staging vike build`.)
17
+ const skipNodeModules = '/node_modules/';
18
+ const skipIrrelevant = 'import.meta.env.';
19
+ const filterRolldown = {
20
+ id: {
21
+ exclude: `**${skipNodeModules}**`,
22
+ },
23
+ code: {
24
+ include: skipIrrelevant,
25
+ },
26
+ };
27
+ const filterFunction = (id, code) => {
28
+ if (id.includes(skipNodeModules))
29
+ return false;
30
+ if (!code.includes(skipIrrelevant))
31
+ return false;
32
+ return true;
33
+ };
34
+ function pluginReplaceConstantsEnvVars() {
35
+ let envVarsAll;
36
+ let envPrefix;
37
+ let config;
38
+ return [
39
+ {
40
+ name: 'vike:pluginReplaceConstantsEnvVars',
41
+ enforce: 'post',
42
+ configResolved: {
43
+ handler(config_) {
44
+ config = config_;
45
+ envVarsAll = loadEnv(config.mode, config.envDir || config.root, '');
46
+ envPrefix = getEnvPrefix(config);
47
+ config.plugins.sort(lowerFirst((plugin) => (plugin.name === 'vite:define' ? 1 : 0)));
48
+ },
49
+ },
50
+ transform: {
51
+ filter: filterRolldown,
52
+ handler(code, id, options) {
53
+ id = normalizeId(id);
54
+ assertPosixPath(id);
55
+ assertPosixPath(config.root);
56
+ if (!id.startsWith(config.root))
57
+ return; // skip linked dependencies
58
+ assert(filterFunction(id, code));
59
+ const isBuild = config.command === 'build';
60
+ const isClientSide = !isViteServerSide_extraSafe(config, this.environment, options);
61
+ const { magicString, getMagicStringResult } = getMagicString(code, id);
62
+ // Get regex operations
63
+ const replacements = Object.entries(envVarsAll)
64
+ // Skip env vars that start with [`config.envPrefix`](https://vite.dev/config/shared-options.html#envprefix) — they are already handled by Vite
65
+ .filter(([envName]) => !envPrefix.some((prefix) => envName.startsWith(prefix)))
66
+ // Skip constants like import.meta.env.DEV which are already handled by Vite
67
+ .filter(([envName]) => !['DEV', 'PROD', 'SSR', 'MODE', 'BASE_URL'].includes(envName))
68
+ .map(([envName, envVal]) => {
69
+ const envStatement = `import.meta.env.${envName}`;
70
+ const envStatementRegExpStr = escapeRegex(envStatement) + '\\b';
71
+ // Show error (warning in dev) if client code contains a private environment variable (one that doesn't start with PUBLIC_ENV__ and that isn't included in `PUBLIC_ENV_ALLOWLIST`).
72
+ if (isClientSide) {
73
+ const skip = assertNoClientSideLeak({
74
+ envName,
75
+ envStatement,
76
+ envStatementRegExpStr,
77
+ code,
78
+ id,
79
+ config,
80
+ isBuild,
81
+ });
82
+ if (skip)
83
+ return null;
84
+ }
85
+ return { regExpStr: envStatementRegExpStr, replacement: envVal };
86
+ })
87
+ .filter(isNotNullish);
88
+ // Apply regex operations
89
+ replacements.forEach(({ regExpStr, replacement }) => {
90
+ magicString.replaceAll(new RegExp(regExpStr, 'g'), JSON.stringify(replacement));
91
+ });
92
+ return getMagicStringResult();
93
+ },
94
+ },
95
+ },
96
+ ];
97
+ }
98
+ function getEnvPrefix(config) {
99
+ const { envPrefix } = config;
100
+ if (!envPrefix)
101
+ return [];
102
+ if (!isArray(envPrefix))
103
+ return [envPrefix];
104
+ return envPrefix;
105
+ }
106
+ function assertNoClientSideLeak({ envName, envStatement, envStatementRegExpStr, code, id, config, isBuild, }) {
107
+ const isPrivate = !envName.startsWith(PUBLIC_ENV_PREFIX) && !PUBLIC_ENV_ALLOWLIST.includes(envName);
108
+ // ✅ All good
109
+ if (!isPrivate)
110
+ return;
111
+ if (!new RegExp(envStatementRegExpStr).test(code))
112
+ return true;
113
+ // ❌ Security leak!
114
+ // - Warning in dev
115
+ // - assertUsage() and abort when building for production
116
+ const modulePath = getFilePathToShowToUserModule(id, config);
117
+ const errMsgAddendum = isBuild ? '' : ' (Vike will prevent your app from building for production)';
118
+ const envNameFixed = `${PUBLIC_ENV_PREFIX}${envName}`;
119
+ const errMsg = `${envStatement} is used in client-side file ${modulePath} which means that the environment variable ${envName} will be included in client-side bundles and, therefore, ${envName} will be publicly exposed which can be a security leak${errMsgAddendum}. Use ${envStatement} only in server-side files, or rename ${envName} to ${envNameFixed}, see https://vike.dev/env`;
120
+ if (isBuild) {
121
+ assertUsage(false, errMsg);
122
+ }
123
+ else {
124
+ // - Only a warning for faster development DX (e.g. when user toggles `ssr: boolean` or `onBeforeRenderIsomorph: boolean`).
125
+ // - Although only showing a warning can be confusing: https://github.com/vikejs/vike/issues/1641
126
+ assertWarning(false, errMsg, { onlyOnce: true });
127
+ }
128
+ assert(!isBuild); // we should abort if building for production
129
+ }
@@ -0,0 +1,10 @@
1
+ export { pluginReplaceConstantsGlobalThis };
2
+ import type { Plugin } from 'vite';
3
+ declare global {
4
+ /** Like `import.meta.env.DEV` but works for `node_modules/` packages with `ssr.external` */
5
+ var __VIKE__IS_DEV: boolean;
6
+ /** Like `import.meta.env.SSR` but works for `node_modules/` packages with `ssr.external` */
7
+ var __VIKE__IS_CLIENT: boolean;
8
+ var __VIKE__IS_DEBUG: boolean;
9
+ }
10
+ declare function pluginReplaceConstantsGlobalThis(): Plugin[];
@@ -0,0 +1,77 @@
1
+ export { pluginReplaceConstantsGlobalThis };
2
+ import { assert, isDebug, addVirtualFileIdPrefix, escapeRegex } from '../utils.js';
3
+ import { isViteServerSide_applyToEnvironment, isViteServerSide_configEnvironment, isViteServerSide_extraSafe, } from '../shared/isViteServerSide.js';
4
+ const isDebugVal = isDebug();
5
+ globalThis.__VIKE__IS_CLIENT = false;
6
+ globalThis.__VIKE__IS_DEBUG = isDebugVal;
7
+ const VIRTUAL_FILE_ID = 'virtual:vike:server:globalThis-constants';
8
+ const filterRolldown = {
9
+ id: {
10
+ include: new RegExp(escapeRegex(VIRTUAL_FILE_ID)),
11
+ },
12
+ };
13
+ const filterFunction = (id) => id === VIRTUAL_FILE_ID || id === addVirtualFileIdPrefix(VIRTUAL_FILE_ID);
14
+ function pluginReplaceConstantsGlobalThis() {
15
+ let config;
16
+ let isDev;
17
+ return [
18
+ {
19
+ name: 'vike:pluginReplaceConstantsGlobalThis:define',
20
+ config: {
21
+ handler(config) {
22
+ assert(typeof config._isDev === 'boolean');
23
+ isDev = config._isDev;
24
+ globalThis.__VIKE__IS_DEV = isDev;
25
+ return {
26
+ define: {
27
+ 'globalThis.__VIKE__IS_DEV': JSON.stringify(isDev),
28
+ 'globalThis.__VIKE__IS_DEBUG': JSON.stringify(isDebugVal),
29
+ },
30
+ };
31
+ },
32
+ },
33
+ configEnvironment: {
34
+ handler(name, config) {
35
+ const isClientSide = !isViteServerSide_configEnvironment(name, config);
36
+ return {
37
+ define: {
38
+ 'globalThis.__VIKE__IS_CLIENT': JSON.stringify(isClientSide),
39
+ },
40
+ };
41
+ },
42
+ },
43
+ configResolved(config_) {
44
+ config = config_;
45
+ },
46
+ },
47
+ {
48
+ name: 'vike:pluginReplaceConstantsGlobalThis:virtual-file',
49
+ // We only need the virtual file for the server-side (for node_modules/ packages with ssr.external) — the `define` values above always apply to the client-side.
50
+ applyToEnvironment(env) {
51
+ return isViteServerSide_applyToEnvironment(env);
52
+ },
53
+ resolveId: {
54
+ filter: filterRolldown,
55
+ handler(id) {
56
+ assert(filterFunction(id));
57
+ assert(id === VIRTUAL_FILE_ID);
58
+ return addVirtualFileIdPrefix(id);
59
+ },
60
+ },
61
+ load: {
62
+ filter: filterRolldown,
63
+ handler(id, options) {
64
+ assert(filterFunction(id));
65
+ assert(isViteServerSide_extraSafe(config, this.environment, options));
66
+ assert(typeof isDev === 'boolean');
67
+ const code = [
68
+ `globalThis.__VIKE__IS_DEV = ${JSON.stringify(isDev)};`,
69
+ `globalThis.__VIKE__IS_CLIENT = false;`,
70
+ `globalThis.__VIKE__IS_DEBUG = ${JSON.stringify(isDebugVal)};`,
71
+ ].join('\n');
72
+ return code;
73
+ },
74
+ },
75
+ },
76
+ ];
77
+ }
@@ -0,0 +1,3 @@
1
+ export { pluginReplaceConstantsPageContext };
2
+ import type { Plugin } from 'vite';
3
+ declare function pluginReplaceConstantsPageContext(): Plugin[];
@@ -1,4 +1,4 @@
1
- export { pluginReplaceIsClientSide };
1
+ export { pluginReplaceConstantsPageContext };
2
2
  import { assert, assertPosixPath } from '../utils.js';
3
3
  import { normalizeId } from '../shared/normalizeId.js';
4
4
  import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
@@ -9,6 +9,8 @@ const constantsIsClientSide = [
9
9
  'globalContext.isClientSide',
10
10
  'pageContext.globalContext.isClientSide',
11
11
  ];
12
+ // - See https://vike.dev/pageContext#narrowing-down
13
+ // - We cannot use [`define`](https://vite.dev/config/shared-options.html#define) because of https://github.com/rolldown/rolldown/issues/4300
12
14
  const skipNodeModules = '/node_modules/';
13
15
  const skipIrrelevant = 'Context.isClientSide';
14
16
  assert(constantsIsClientSide.every((constant) => constant.endsWith(skipIrrelevant)));
@@ -27,11 +29,11 @@ const filterFunction = (id, code) => {
27
29
  return false;
28
30
  return true;
29
31
  };
30
- function pluginReplaceIsClientSide() {
32
+ function pluginReplaceConstantsPageContext() {
31
33
  let config;
32
34
  return [
33
35
  {
34
- name: 'vike:pluginReplaceIsClientSide',
36
+ name: 'vike:pluginReplaceConstantsPageContext',
35
37
  enforce: 'post',
36
38
  apply: 'build',
37
39
  configResolved: {
@@ -12,6 +12,9 @@ function getCode(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, isCl
12
12
  const lines = [];
13
13
  const importStatements = [];
14
14
  const filesEnv = new Map();
15
+ if (!isForClientSide) {
16
+ importStatements.push("import 'virtual:vike:server:globalThis-constants';");
17
+ }
15
18
  lines.push('export const pageConfigsSerialized = [');
16
19
  lines.push(getCodePageConfigsSerialized(pageConfigs, isForClientSide, isClientRouting, isDev, importStatements, filesEnv));
17
20
  lines.push('];');
@@ -22,7 +25,10 @@ function getCode(pageConfigs, pageConfigGlobal, isForClientSide, isDev, id, isCl
22
25
  // https://vite.dev/guide/api-environment-frameworks.html
23
26
  lines.push('if (import.meta.hot) import.meta.hot.accept();');
24
27
  }
25
- const code = [...importStatements, ...lines].join('\n');
28
+ let code = [...importStatements, ...lines].join('\n');
29
+ if (!isForClientSide) {
30
+ code = "import 'virtual:vike:server:globalThis-constants';\n" + code;
31
+ }
26
32
  debug(id, isForClientSide ? 'CLIENT-SIDE' : 'SERVER-SIDE', code);
27
33
  return code;
28
34
  }
@@ -23,6 +23,9 @@ async function getCode(config, isForClientSide, isClientRouting, isDev, id) {
23
23
  const isBuild = command === 'build';
24
24
  assert(isDev === !isBuild);
25
25
  let content = '';
26
+ if (!isForClientSide) {
27
+ content += "import 'virtual:vike:server:globalThis-constants';\n";
28
+ }
26
29
  {
27
30
  const globRoots = getGlobRoots(config);
28
31
  debugGlob('Glob roots: ', globRoots);
@@ -7,7 +7,7 @@ import { parseVirtualFileId } from '../../shared/virtualFileId.js';
7
7
  import { reloadVikeConfig, isV1Design, getVikeConfigInternalOptional } from '../shared/resolveVikeConfigInternal.js';
8
8
  import pc from '@brillout/picocolors';
9
9
  import { logConfigInfo } from '../shared/loggerNotProd.js';
10
- import { getModuleFilePathAbsolute } from '../shared/getFilePath.js';
10
+ import { getFilePathToShowToUserModule } from '../shared/getFilePath.js';
11
11
  import { isRunnable, updateUserFiles } from '../../runtime/globalContext.js';
12
12
  import { isPlusFile } from '../shared/resolveVikeConfigInternal/crawlPlusFiles.js';
13
13
  import { isTemporaryBuildFile } from '../shared/resolveVikeConfigInternal/transpileAndExecuteFile.js';
@@ -176,7 +176,7 @@ function reloadConfig(filePath, config, op, server) {
176
176
  // Ensure server.ssrLoadModule() loads fresh Vike virtual files (`reloadConfig()` > `updateUserFiles()` > `server.ssrLoadModule()`)
177
177
  invalidateVikeVirtualFiles(server);
178
178
  {
179
- const filePathToShowToUserResolved = getModuleFilePathAbsolute(filePath, config);
179
+ const filePathToShowToUserResolved = getFilePathToShowToUserModule(filePath, config);
180
180
  const msg = `${op} ${pc.dim(filePathToShowToUserResolved)}`;
181
181
  logConfigInfo(msg, 'info');
182
182
  }
@@ -1,9 +1,8 @@
1
1
  export { getFilePathResolved };
2
2
  export { getFilePathUnresolved };
3
3
  export { getFilePathAbsoluteUserRootDir };
4
- export { getFilePathToShowToUserFromUnknown };
5
- export { getModuleFilePathAbsolute };
6
- export { getModuleFilePathRelative };
4
+ export { getFilePathToShowToUserUnknown };
5
+ export { getFilePathToShowToUserModule };
7
6
  export { cleanFilePathUnknown };
8
7
  export { assertModuleId };
9
8
  import type { FilePathResolved, FilePathUnresolved } from '../../../types/FilePath.js';
@@ -24,8 +23,7 @@ declare function getFilePathAbsoluteUserRootDir({ filePathAbsoluteFilesystem, us
24
23
  filePathAbsoluteFilesystem: string;
25
24
  userRootDir: string;
26
25
  }): string | null;
27
- declare function getModuleFilePathAbsolute(moduleId: string, config: ResolvedConfig): string;
28
- declare function getModuleFilePathRelative(moduleId: string, config: ResolvedConfig): string;
26
+ declare function getFilePathToShowToUserModule(moduleId: string, config: ResolvedConfig): string;
29
27
  declare function assertModuleId(moduleId: string): void;
30
- declare function getFilePathToShowToUserFromUnknown(filePathUnknown: string, userRootDir: string): string;
28
+ declare function getFilePathToShowToUserUnknown(filePathUnknown: string, userRootDir: string): string;
31
29
  declare function cleanFilePathUnknown(filePathUnknown: string): string;
@@ -1,9 +1,8 @@
1
1
  export { getFilePathResolved };
2
2
  export { getFilePathUnresolved };
3
3
  export { getFilePathAbsoluteUserRootDir };
4
- export { getFilePathToShowToUserFromUnknown };
5
- export { getModuleFilePathAbsolute };
6
- export { getModuleFilePathRelative };
4
+ export { getFilePathToShowToUserUnknown };
5
+ export { getFilePathToShowToUserModule };
7
6
  export { cleanFilePathUnknown };
8
7
  export { assertModuleId };
9
8
  import path from 'node:path';
@@ -107,15 +106,11 @@ function getFilePathRelative({ filePathAbsoluteFilesystem, userRootDir, }) {
107
106
  return { filePathAbsoluteUserRootDir, filePathRelativeUserRootDir };
108
107
  }
109
108
  }
110
- function getModuleFilePathAbsolute(moduleId, config) {
111
- const { filePathAbsoluteUserRootDir, filePathAbsoluteFilesystem } = getModuleFilePath(moduleId, config);
109
+ function getFilePathToShowToUserModule(moduleId, config) {
110
+ const { filePathAbsoluteUserRootDir, filePathAbsoluteFilesystem } = getFilePathModule(moduleId, config);
112
111
  return filePathAbsoluteUserRootDir || filePathAbsoluteFilesystem;
113
112
  }
114
- function getModuleFilePathRelative(moduleId, config) {
115
- const { filePathRelativeUserRootDir } = getModuleFilePath(moduleId, config);
116
- return filePathRelativeUserRootDir;
117
- }
118
- function getModuleFilePath(moduleId, config) {
113
+ function getFilePathModule(moduleId, config) {
119
114
  const userRootDir = config.root;
120
115
  assertModuleId(moduleId);
121
116
  assertPosixPath(userRootDir);
@@ -132,7 +127,7 @@ function assertModuleId(moduleId) {
132
127
  assertPosixPath(moduleId);
133
128
  assertFilePathAbsoluteFilesystem(moduleId); // Can moduleId be something else than the filesystem absolute path?
134
129
  }
135
- function getFilePathToShowToUserFromUnknown(
130
+ function getFilePathToShowToUserUnknown(
136
131
  // We don't have any guarantee about filePath, e.g. about whether is filePathAbsoluteFilesystem or filePathAbsoluteUserRootDir
137
132
  filePathUnknown, userRootDir) {
138
133
  assertPosixPath(userRootDir);
@@ -1,18 +1,21 @@
1
1
  export { isViteServerSide };
2
- export { isViteClientSide };
3
2
  export { isViteServerSide_viteEnvOptional };
4
3
  export { isViteServerSide_onlySsrEnv };
5
4
  export { isViteServerSide_extraSafe };
5
+ export { isViteServerSide_applyToEnvironment };
6
+ export { isViteServerSide_configEnvironment };
6
7
  export type { ViteEnv };
7
- import type { Environment, EnvironmentOptions, ResolvedConfig, UserConfig } from 'vite';
8
+ import type { Environment, EnvironmentOptions, ResolvedConfig, UserConfig, Plugin } from 'vite';
8
9
  type ViteEnv = {
9
10
  name?: string;
10
11
  config: EnvironmentOptions | Environment['config'];
11
12
  };
12
13
  declare function isViteServerSide(configGlobal: ResolvedConfig | UserConfig, viteEnv: ViteEnv): boolean;
13
14
  declare function isViteServerSide_viteEnvOptional(configGlobal: ResolvedConfig | UserConfig, viteEnv?: ViteEnv | undefined): boolean;
14
- declare function isViteClientSide(configGlobal: ResolvedConfig, viteEnv: ViteEnv): boolean;
15
15
  declare function isViteServerSide_onlySsrEnv(configGlobal: ResolvedConfig, viteEnv: ViteEnv): boolean;
16
16
  declare function isViteServerSide_extraSafe(config: ResolvedConfig, viteEnv: ViteEnv, options: {
17
17
  ssr?: boolean;
18
18
  } | undefined): boolean;
19
+ type PartialEnvironment = Parameters<NonNullable<Plugin['applyToEnvironment']>>[0];
20
+ declare function isViteServerSide_applyToEnvironment(env: PartialEnvironment): boolean;
21
+ declare function isViteServerSide_configEnvironment(name: string, config: EnvironmentOptions): boolean;
@@ -1,8 +1,9 @@
1
1
  export { isViteServerSide };
2
- export { isViteClientSide };
3
2
  export { isViteServerSide_viteEnvOptional };
4
3
  export { isViteServerSide_onlySsrEnv };
5
4
  export { isViteServerSide_extraSafe };
5
+ export { isViteServerSide_applyToEnvironment };
6
+ export { isViteServerSide_configEnvironment };
6
7
  import { assert } from '../../../utils/assert.js';
7
8
  function isViteServerSide_impl(configGlobal, viteEnv) {
8
9
  assert(!('consumer' in configGlobal)); // make sure configGlobal isn't viteEnv.config
@@ -42,9 +43,6 @@ function isViteServerSide(configGlobal, viteEnv) {
42
43
  function isViteServerSide_viteEnvOptional(configGlobal, viteEnv) {
43
44
  return isViteServerSide_impl(configGlobal, viteEnv);
44
45
  }
45
- function isViteClientSide(configGlobal, viteEnv) {
46
- return !isViteServerSide(configGlobal, viteEnv);
47
- }
48
46
  // Only `ssr` env: for example don't include `vercel_edge` nor `vercel_node`.
49
47
  function isViteServerSide_onlySsrEnv(configGlobal, viteEnv) {
50
48
  return viteEnv.name ? viteEnv.name === 'ssr' : isViteServerSide(configGlobal, viteEnv);
@@ -64,3 +62,14 @@ function isViteServerSide_extraSafe(config, viteEnv, options) {
64
62
  assert(options.ssr === isServerSide, debug);
65
63
  return isServerSide;
66
64
  }
65
+ function isViteServerSide_applyToEnvironment(env) {
66
+ const { consumer } = env.config;
67
+ return isViteServerSide_consumer(consumer);
68
+ }
69
+ function isViteServerSide_configEnvironment(name, config) {
70
+ const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');
71
+ return isViteServerSide_consumer(consumer);
72
+ }
73
+ function isViteServerSide_consumer(consumer) {
74
+ return consumer !== 'client';
75
+ }
@@ -8,7 +8,7 @@ export { getPrettyErrMessage };
8
8
  // Copied & adapted from https://github.com/vitejs/vite/blob/9c114c5c72a6af87e3330d5573362554b4511265/packages/vite/src/node/server/middlewares/error.ts
9
9
  import pc from '@brillout/picocolors';
10
10
  import { assert, escapeRegex, isObject, removeEmptyLines, stripAnsi } from '../../utils.js';
11
- import { cleanFilePathUnknown, getFilePathToShowToUserFromUnknown } from '../getFilePath.js';
11
+ import { cleanFilePathUnknown, getFilePathToShowToUserUnknown } from '../getFilePath.js';
12
12
  function isErrorWithCodeSnippet(err) {
13
13
  if (!isObject(err)) {
14
14
  return false;
@@ -47,7 +47,7 @@ function getPrettyErrorWithCodeSnippet(err, userRootDir) {
47
47
  let { id, frame } = err;
48
48
  const msgFirstLine = [
49
49
  pc.red('Failed to transpile'),
50
- pc.bold(pc.red(getFilePathToShowToUserFromUnknown(id, userRootDir))),
50
+ pc.bold(pc.red(getFilePathToShowToUserUnknown(id, userRootDir))),
51
51
  pc.red('because:'),
52
52
  ].join(' ');
53
53
  const errMsg = getPrettyErrMessage(err);