vike 0.4.259-commit-85c5e84 → 0.4.259-commit-dcc116b

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.
@@ -5,7 +5,7 @@ export { getViteRoot };
5
5
  export { assertViteRoot };
6
6
  export { normalizeViteRoot };
7
7
  import { loadConfigFromFile, mergeConfig, resolveConfig } from 'vite';
8
- import { getVikeConfigInternal, getVikeConfigFromCliOrEnv, setVikeConfigContext, isVikeConfigContextSet, } from '../vite/shared/resolveVikeConfigInternal.js';
8
+ import { getVikeConfigInternal, getVikeConfigFromCliOrEnv, setVikeConfigContext, isVikeConfigContextSet, EARLY_SETTINGS, } from '../vite/shared/resolveVikeConfigInternal.js';
9
9
  import path from 'node:path';
10
10
  import { assert, assertUsage, assertWarning } from '../../utils/assert.js';
11
11
  import { getGlobalObject } from '../../utils/getGlobalObject.js';
@@ -53,27 +53,38 @@ async function getViteRoot(viteContext) {
53
53
  assert(globalObject.root);
54
54
  return globalObject.root;
55
55
  }
56
+ // TODO rename to resolveViteConfig
57
+ // TODO rename_all viteConfigFromUser viteConfigFrom
58
+ // TODO rename_all vikeConfigFromUser vikeConfigFrom
56
59
  async function getViteInfo(viteContext) {
57
- const { viteConfigFromUserVikeApiOptions } = getVikeApiContext();
58
- let viteConfigFromUserResolved = clone(viteConfigFromUserVikeApiOptions ?? {});
59
60
  // Precedence:
60
61
  // 1. (highest precedence) | viteConfigFromUserEnvVar | VITE_CONFIG
61
- // 2. | viteConfigFromUserVikeMode | VIKE_CONFIG & Vike CLI options — only `+mode`
62
+ // 2. | viteConfigFromVikeCliOrEnv | VIKE_CONFIG & Vike CLI options — `+mode` & `+root`
62
63
  // 3. | viteConfigFromUserViteCli | Vite CLI args — `[root]` & `-c/--config`
63
- // 4. | viteConfigFromUserVikeApiOptions | Vike API options
64
+ // 4. | viteConfigFromUserVikeApiOptions | Vike API options — `viteConfig`, and `+mode` & `+root` from `vikeConfig`
64
65
  // 5. (lowest precedence) | viteConfigFromUserViteConfigFile | vite.config.js
65
- // Resolve Vite CLI args (when invoked via Vite's CLI rather than Vike's API).
66
- // Without this, Vike loads vite.config.js blind to `vite [root]` / `-c <file>` and
67
- // ends up with the wrong root when those Vite CLI args are used.
66
+ let viteConfigFromUserResolved = {};
67
+ // Vike API args
68
+ const { viteConfigFromUserVikeApiOptions, vikeConfigFromUserVikeApiOptions } = getVikeApiContext();
69
+ // - Resolve `viteConfig` set over Vike's API
70
+ viteConfigFromUserResolved = merge(viteConfigFromUserResolved, viteConfigFromUserVikeApiOptions ?? {});
71
+ // - Resolve +mode/+root set over Vike's API
72
+ {
73
+ const viteConfigFromVikeApi2 = pick(vikeConfigFromUserVikeApiOptions ?? {}, EARLY_SETTINGS);
74
+ viteConfigFromUserResolved = merge(viteConfigFromUserResolved ?? {}, viteConfigFromVikeApi2);
75
+ }
76
+ // Vite CLI args (when invoked via Vite's CLI rather than Vike's API).
77
+ // - Without this, Vike loads vite.config.js blind to `vite [root]` / `-c <file>` and ends up with the wrong root when those Vite CLI args are used.
68
78
  const viteConfigFromUserViteCli = getViteCliArgs();
69
79
  if (viteConfigFromUserViteCli) {
70
80
  viteConfigFromUserResolved = merge(viteConfigFromUserResolved ?? {}, viteConfigFromUserViteCli);
71
81
  }
72
- // Resolve Vike's +mode setting
82
+ // Vike's CLI and VIKE_CONFIG
83
+ // - Resolve +mode/+root set over Vike's CLI or VIKE_CONFIG
73
84
  {
74
- const viteConfigFromUserVikeMode = pick(getVikeConfigFromCliOrEnv().vikeConfigFromCliOrEnv, ['mode']);
75
- if (Object.keys(viteConfigFromUserVikeMode).length > 0) {
76
- viteConfigFromUserResolved = merge(viteConfigFromUserResolved ?? {}, viteConfigFromUserVikeMode);
85
+ const viteConfigFromVikeCliOrEnv = pick(getVikeConfigFromCliOrEnv().vikeConfigFromCliOrEnv, EARLY_SETTINGS);
86
+ if (Object.keys(viteConfigFromVikeCliOrEnv).length > 0) {
87
+ viteConfigFromUserResolved = merge(viteConfigFromUserResolved ?? {}, viteConfigFromVikeCliOrEnv);
77
88
  }
78
89
  }
79
90
  // Resolve VITE_CONFIG
@@ -85,7 +96,7 @@ async function getViteInfo(viteContext) {
85
96
  globalObject.isOnlyResolvingUserConfig = true;
86
97
  const viteConfigFromUserViteConfigFile = await loadViteConfigFile(viteConfigFromUserResolved, viteContext);
87
98
  globalObject.isOnlyResolvingUserConfig = false;
88
- // Correct precedence, replicates Vite:
99
+ // Lowest precedence. The `merge()` applies the correct precedence and replicates Vite:
89
100
  // https://github.com/vitejs/vite/blob/4f5845a3182fc950eb9cd76d7161698383113b18/packages/vite/src/node/config.ts#L1001
90
101
  const viteConfigResolved = merge(viteConfigFromUserViteConfigFile ?? {}, viteConfigFromUserResolved ?? {});
91
102
  const root = normalizeViteRoot(viteConfigResolved.root ?? process.cwd());
@@ -122,9 +133,6 @@ async function getViteInfo(viteContext) {
122
133
  function merge(c1, c2) {
123
134
  return mergeConfig(c1, c2);
124
135
  }
125
- function clone(c) {
126
- return mergeConfig({}, c);
127
- }
128
136
  function findVikeVitePlugin(viteConfig) {
129
137
  let vikeVitePluginOptions;
130
138
  let vikeVitePuginFound = false;
@@ -198,11 +206,12 @@ function getViteContextWithOperation(operation) {
198
206
  function getVikeApiContext() {
199
207
  const vikeApiOperation = getVikeApiOperation();
200
208
  if (!vikeApiOperation)
201
- return { viteConfigFromUserVikeApiOptions: null, viteContext: null };
209
+ return { viteConfigFromUserVikeApiOptions: null, vikeConfigFromUserVikeApiOptions: null, viteContext: null };
202
210
  const { options, operation } = vikeApiOperation;
203
211
  const viteConfigFromUserVikeApiOptions = options.viteConfig;
212
+ const vikeConfigFromUserVikeApiOptions = options.vikeConfig;
204
213
  const viteContext = getViteContextWithOperation(operation);
205
- return { viteConfigFromUserVikeApiOptions, viteContext };
214
+ return { viteConfigFromUserVikeApiOptions, vikeConfigFromUserVikeApiOptions, viteContext };
206
215
  }
207
216
  function resolveViteContext(inlineConfig = {}, viteContext) {
208
217
  const isBuild = viteContext === 'build';
@@ -29,28 +29,41 @@ function getCommand() {
29
29
  function getCliOptions() {
30
30
  let cliOptions = {};
31
31
  let configNameCurrent;
32
- const commitIfDefinedWithoutValue = () => {
32
+ const addConfig = (configValue) => {
33
+ assert(configNameCurrent);
34
+ cliOptions[configNameCurrent] = configValue;
35
+ configNameCurrent = undefined;
36
+ };
37
+ const addConfigWithoutValue = () => {
33
38
  if (configNameCurrent)
34
- commit(true);
39
+ addConfig(true);
35
40
  };
36
- const commit = (val) => {
41
+ const addConfigWithValue = (configValueStr) => {
37
42
  assert(configNameCurrent);
38
- cliOptions[configNameCurrent] = val;
39
- configNameCurrent = undefined;
43
+ addConfig(parseJson5(configValueStr, `CLI option --${configNameCurrent}`));
40
44
  };
41
45
  for (const arg of process.argv.slice(3)) {
42
46
  showHelpOrVersion(arg);
43
47
  if (arg.startsWith('--')) {
44
- commitIfDefinedWithoutValue();
45
- configNameCurrent = arg.slice('--'.length);
48
+ addConfigWithoutValue();
49
+ const str = arg.slice('--'.length);
50
+ const eqIdx = str.indexOf('=');
51
+ if (eqIdx === -1) {
52
+ configNameCurrent = str;
53
+ }
54
+ else {
55
+ configNameCurrent = str.slice(0, eqIdx);
56
+ const configValueStr = str.slice(eqIdx + 1);
57
+ addConfigWithValue(configValueStr);
58
+ }
46
59
  }
47
60
  else {
48
61
  if (!configNameCurrent)
49
62
  wrongUsage(`Unknown option ${pc.bold(arg)}`);
50
- commit(parseJson5(arg, `CLI option --${configNameCurrent}`));
63
+ addConfigWithValue(arg);
51
64
  }
52
65
  }
53
- commitIfDefinedWithoutValue();
66
+ addConfigWithoutValue();
54
67
  return cliOptions;
55
68
  }
56
69
  function showHelp() {
@@ -65,9 +78,10 @@ function showHelp() {
65
78
  'Common CLI options:',
66
79
  [
67
80
  `vike dev ${pc.cyan('--host')} ${TAB}${pc.dim('# Make server available over LAN and public addresses')}`,
68
- `vike dev ${pc.cyan('--port')} 80 ${TAB}${pc.dim('# Change the server port')}`,
69
- `vike build ${pc.cyan('--mode')} staging${TAB}${pc.dim('# Set the mode to run in')}`,
81
+ `vike dev ${pc.cyan('--port')} 80 ${TAB}${pc.dim('# Set server port')}`,
82
+ `vike build ${pc.cyan('--mode')} staging${TAB}${pc.dim('# Set mode (e.g. development, production, staging)')}`,
70
83
  `vike dev ${pc.cyan('--force')} ${TAB}${pc.dim("# Disable Vite's cache")}`,
84
+ `vike dev ${pc.cyan('--root')} src ${TAB}${pc.dim('# Set project root directory')}`,
71
85
  ]
72
86
  .map((o) => ` ${pc.dim('$')} ${o}`)
73
87
  .join('\n'),
@@ -3,6 +3,7 @@ export { resolveOptimizeDeps };
3
3
  import { findPageFiles } from '../../shared/findPageFiles.js';
4
4
  import { assert } from '../../../../utils/assert.js';
5
5
  import { createDebug } from '../../../../utils/debug.js';
6
+ import { deepEqual } from '../../../../utils/deepEqual.js';
6
7
  import { isArray } from '../../../../utils/isArray.js';
7
8
  import { isFilePathAbsoluteFilesystem } from '../../../../utils/isFilePathAbsoluteFilesystem.js';
8
9
  import { assertImportIsNpmPackage, getNpmPackageName } from '../../../../utils/parseNpmPackage.js';
@@ -70,9 +71,9 @@ const optimizeDeps = {
70
71
  // - Make server environments inherit from ssr.optimizeDeps (it isn't the case by default)
71
72
  async function resolveOptimizeDeps(config) {
72
73
  const vikeConfig = await getVikeConfigInternal();
73
- const { _pageConfigs: pageConfigs } = vikeConfig;
74
+ const { _pageConfigs: pageConfigs, _pageConfigGlobal: pageConfigGlobal } = vikeConfig;
74
75
  // Retrieve user's + files (i.e. Vike entries)
75
- const { entriesClient, entriesServer, includeClient, includeServer } = await getPageDeps(config, pageConfigs);
76
+ const { entriesClient, entriesServer, includeClient, includeServer } = await getPageDeps(config, pageConfigs, pageConfigGlobal);
76
77
  // Add late discovered dependencies, if they exist
77
78
  LATE_DISCOVERED.forEach((dep) => {
78
79
  const userRootDir = config.root;
@@ -114,18 +115,19 @@ async function resolveOptimizeDeps(config) {
114
115
  env.optimizeDeps.entries = remove(env.optimizeDeps.entries ?? []);
115
116
  }
116
117
  // Debug
117
- if (debug.isActivated)
118
- debug('optimizeDeps', {
119
- 'config.optimizeDeps.entries': config.optimizeDeps.entries,
120
- 'config.optimizeDeps.include': config.optimizeDeps.include,
121
- 'config.optimizeDeps.exclude': config.optimizeDeps.exclude,
122
- // @ts-ignore Vite doesn't seem to support ssr.optimizeDeps.entries (vite@7.0.6, July 2025)
123
- 'config.ssr.optimizeDeps.entries': config.ssr.optimizeDeps.entries,
124
- 'config.ssr.optimizeDeps.include': config.ssr.optimizeDeps.include,
125
- 'config.ssr.optimizeDeps.exclude': config.ssr.optimizeDeps.exclude,
126
- });
118
+ if (debug.isActivated) {
119
+ const envs = {};
120
+ for (const envName in config.environments) {
121
+ const env = config.environments[envName];
122
+ envs[`config.environments.${envName}.optimizeDeps.entries`] = env.optimizeDeps.entries;
123
+ envs[`config.environments.${envName}.optimizeDeps.include`] = env.optimizeDeps.include;
124
+ envs[`config.environments.${envName}.optimizeDeps.exclude`] = env.optimizeDeps.exclude;
125
+ }
126
+ debug('optimizeDeps', envs);
127
+ assertEnvsInSyncWithLegacy(config);
128
+ }
127
129
  }
128
- async function getPageDeps(config, pageConfigs) {
130
+ async function getPageDeps(config, pageConfigs, pageConfigGlobal) {
129
131
  let entriesClient = [];
130
132
  let entriesServer = [];
131
133
  let includeClient = [];
@@ -181,7 +183,8 @@ async function getPageDeps(config, pageConfigs) {
181
183
  {
182
184
  ;
183
185
  [true, false].forEach((isForClientSide) => {
184
- pageConfigs.forEach((pageConfig) => {
186
+ ;
187
+ [...pageConfigs, pageConfigGlobal].forEach((pageConfig) => {
185
188
  Object.entries(pageConfig.configValueSources).forEach(([configName]) => {
186
189
  const runtimeEnv = {
187
190
  isForClientSide,
@@ -213,10 +216,15 @@ async function getPageDeps(config, pageConfigs) {
213
216
  });
214
217
  }
215
218
  // Add virtual files.
216
- // - This doesn't work: Vite's dep optimizer doesn't seem to be able to crawl virtual files.
217
- // - Should we make it work? E.g. by creating a temporary file at node_modules/.vike/virtualFiles.js
218
- // - Or should we remove it? And make sure getPageDeps() also works for aliased import paths
219
- // - If we do, then we need to adjust include/entries (maybe by making include === entries -> will Vite complain?)
219
+ // - Vite 8+ (Rolldown-based dep scanner) crawls virtual IDs natively its scanner routes
220
+ // through `environment.pluginContainer.resolveId()`, so Vike's resolveId/load handlers
221
+ // run during the scan and the virtual file's transitive deps are seen.
222
+ // - Vite ≤7 (esbuild-based dep scanner) cannot crawl virtual IDs those virtuals' deps
223
+ // surface lazily and trigger "✨ new dependencies optimized" reload cycles. As a
224
+ // workaround we could materialize each virtual to a real file under
225
+ // `node_modules/.vike/optimizeDeps-virtuals/`; an implementation lives in the reverted
226
+ // commit https://github.com/vikejs/vike/commit/b068009c3 (re-apply if Vite ≤7 support
227
+ // matters).
220
228
  {
221
229
  const { hasClientRouting, hasServerRouting, clientEntries } = analyzeClientEntries(pageConfigs, config);
222
230
  Object.values(clientEntries).forEach(({ entryTarget, entryFilePath }) => {
@@ -265,3 +273,20 @@ function remove(input) {
265
273
  list = list.filter((e) => !ALWAYS_REMOVE.includes(e));
266
274
  return list;
267
275
  }
276
+ // Sanity-check that the legacy `config.optimizeDeps` and `config.ssr.optimizeDeps` slots
277
+ // stay in sync with the corresponding environment values — so logging only the env values
278
+ // (above) isn't hiding anything.
279
+ function assertEnvsInSyncWithLegacy(config) {
280
+ const client = config.environments.client?.optimizeDeps;
281
+ assert(client);
282
+ assert(deepEqual(config.optimizeDeps.entries, client.entries));
283
+ assert(deepEqual(config.optimizeDeps.include, client.include));
284
+ assert(deepEqual(config.optimizeDeps.exclude, client.exclude));
285
+ const ssr = config.environments.ssr?.optimizeDeps;
286
+ assert(ssr);
287
+ /* Vite doesn't seem to support config.ssr.optimizeDeps.entries (vite@7.0.6, July 2025)
288
+ assert(deepEqual(config.ssr.optimizeDeps.entries, ssr.entries))
289
+ */
290
+ assert(deepEqual(config.ssr.optimizeDeps.include, ssr.include));
291
+ assert(deepEqual(config.ssr.optimizeDeps.exclude, ssr.exclude));
292
+ }
@@ -7,6 +7,5 @@ declare function getServerConfig(vikeConfig: VikeConfigInternal): {
7
7
  serverEntryId: string;
8
8
  serverEntryVike: string;
9
9
  serverFilePath: string | null;
10
- isServerEntry: boolean;
11
10
  } | undefined;
12
11
  declare function isUniversalDeployVitePreview(vikeConfig: VikeConfigInternal, viteConfigResolved: ResolvedConfig): boolean | null;
@@ -1,6 +1,5 @@
1
1
  export { getServerConfig };
2
2
  export { isUniversalDeployVitePreview };
3
- import { dirname, resolve } from 'node:path';
4
3
  import { catchAllEntry } from '@universal-deploy/store';
5
4
  import { assert } from '../../../../utils/assert.js';
6
5
  import '../../assertEnvVite.js';
@@ -8,7 +7,6 @@ function getServerConfig(vikeConfig) {
8
7
  let serverEntryId;
9
8
  let serverFilePath = null;
10
9
  let serverEntryVike;
11
- let isServerEntry = false;
12
10
  // universal-deploy support must be manually enabled
13
11
  const serverConfig =
14
12
  // +config.js > `export default { server: true }`
@@ -23,13 +21,8 @@ function getServerConfig(vikeConfig) {
23
21
  assert('filePathAbsoluteFilesystem' in serverPlusFile.definedAt);
24
22
  serverFilePath = serverPlusFile.definedAt.filePathAbsoluteFilesystem;
25
23
  assert(serverFilePath);
26
- assert(serverPlusFile.valueIsLoaded);
27
- assert(typeof serverPlusFile.value === 'object');
28
- // +server.js > `export default { entry: './server/entrypoint.ts' }`
29
- const entry = serverPlusFile.value.entry;
30
- isServerEntry = typeof entry === 'string';
31
- assert(entry === undefined || isServerEntry);
32
- serverEntryVike = serverEntryId = isServerEntry ? resolve(dirname(serverFilePath), entry) : serverFilePath;
24
+ serverEntryId = serverFilePath;
25
+ serverEntryVike = serverFilePath;
33
26
  }
34
27
  else {
35
28
  serverEntryId = catchAllEntry;
@@ -43,7 +36,6 @@ function getServerConfig(vikeConfig) {
43
36
  // It either points to the default fetchable endpoint (vike/fetch), or one defined by the user through +server.
44
37
  serverEntryVike,
45
38
  serverFilePath,
46
- isServerEntry,
47
39
  };
48
40
  }
49
41
  function isUniversalDeployVitePreview(vikeConfig, viteConfigResolved) {
@@ -24,9 +24,9 @@ function pluginUniversalDeploy(vikeConfig) {
24
24
  assertUsage(target === undefined, `${target} requires +server — see https://vike.dev/server`);
25
25
  }),
26
26
  ];
27
- const { serverEntryVike, serverEntryId, serverFilePath, isServerEntry } = serverConfig;
27
+ const { serverEntryVike, serverEntryId, serverFilePath } = serverConfig;
28
28
  return [
29
- ...universalDeploy({ entry: isServerEntry ? serverEntryVike : undefined }),
29
+ ...universalDeploy(),
30
30
  {
31
31
  name: 'vike:pluginUniversalDeploy:entries',
32
32
  config() {
@@ -1,5 +1,5 @@
1
1
  export { generateVirtualFilePageEntry };
2
- import { assert, getProjectError } from '../../../../utils/assert.js';
2
+ import { assert, getDebugInfoStr, getProjectError } from '../../../../utils/assert.js';
3
3
  import { parseVirtualFileId, generateVirtualFileId } from '../../../../shared-server-node/virtualFileId.js';
4
4
  import { getVikeConfigInternal } from '../../shared/resolveVikeConfigInternal.js';
5
5
  import { extractAssetsAddQuery } from '../../../../shared-server-node/extractAssetsQuery.js';
@@ -26,12 +26,10 @@ async function generateVirtualFilePageEntry(id, isDev) {
26
26
  assert(pageConfig);
27
27
  }
28
28
  else {
29
- /* 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.
30
- assert(pageConfig, { id, pageId })
31
- /*/
32
- if (!pageConfig)
33
- throw getProjectError('Outdated request');
34
- //*/
29
+ if (!pageConfig) {
30
+ // Happens very seldom and can't reproduce reliably. Some kind of HMR race condition? It still happens as of June 2026 with Cloudflare Workers in development — but it isn't blocking, reloading the page fixes the issue.
31
+ throw getProjectError(`Outdated request. Try again. ${getDebugInfoStr({ id, pageId })}`);
32
+ }
35
33
  }
36
34
  const code = getCode(pageConfig, isForClientSide, pageId, resolveIncludeAssetsImportedByServer(vikeConfig.config), isDev);
37
35
  debug(id, isForClientSide ? 'CLIENT-SIDE' : 'SERVER-SIDE', code);
@@ -198,13 +198,22 @@ const metaBuiltIn = {
198
198
  mode: {
199
199
  env: { config: true },
200
200
  global: true,
201
+ /* +mode can't be set in +config.js => a +config.js change never affects it — no Vite restart needed
201
202
  vite: true,
203
+ */
202
204
  },
203
205
  force: {
204
206
  env: { config: true },
205
207
  global: true,
206
208
  vite: true,
207
209
  },
210
+ root: {
211
+ env: { config: true },
212
+ global: true,
213
+ /* +root can't be set in +config.js => a +config.js change never affects it — no Vite restart needed
214
+ vite: true,
215
+ */
216
+ },
208
217
  csp: {
209
218
  env: { server: true },
210
219
  },
@@ -227,7 +236,7 @@ const metaBuiltIn = {
227
236
  global: true,
228
237
  },
229
238
  server: {
230
- env: { server: true, config: true },
239
+ env: { server: true },
231
240
  global: true,
232
241
  },
233
242
  cli: {
@@ -9,6 +9,7 @@ export { isV1Design };
9
9
  export { getConfVal };
10
10
  export { getConfigDefinitionOptional };
11
11
  export { getVikeConfigFromCliOrEnv };
12
+ export { EARLY_SETTINGS };
12
13
  export type { VikeConfigInternal };
13
14
  export type { PageConfigBuildTimeBeforeComputed };
14
15
  import type { PageConfigGlobalBuildTime, ConfigEnv, PageConfigBuildTime, DefinedAtFilePath } from '../../../types/PageConfig.js';
@@ -62,6 +63,7 @@ declare function getVikeConfigFromCliOrEnv(): {
62
63
  configFromCliOptions: import("../../cli/parseCli.js").CliOptions | null;
63
64
  configFromEnvVar: Record<string, unknown> | null;
64
65
  };
66
+ declare const EARLY_SETTINGS: readonly ["root", "mode"];
65
67
  type PageConfigBuildTimeBeforeComputed = Omit<PageConfigBuildTime, 'configValuesComputed'>;
66
68
  declare function getConfigDefinitionOptional(configDefinitions: ConfigDefinitionsInternal, configName: string): {
67
69
  env: ConfigEnv;
@@ -10,6 +10,7 @@ export { isV1Design };
10
10
  export { getConfVal };
11
11
  export { getConfigDefinitionOptional };
12
12
  export { getVikeConfigFromCliOrEnv };
13
+ export { EARLY_SETTINGS };
13
14
  import { deepEqual } from '../../../utils/deepEqual.js';
14
15
  import { assertKeys } from '../../../utils/assertKeys.js';
15
16
  import { assertIsNotProductionRuntime } from '../../../utils/assertSetup.js';
@@ -219,7 +220,8 @@ async function resolveVikeConfigInternal(userRootDir, vikeVitePluginOptions, esb
219
220
  globalObject.isV1Design_ = pageConfigs.length > 0;
220
221
  // Backwards compatibility for vike(options) in vite.config.js
221
222
  temp_interopVikeVitePlugin(pageConfigGlobal, vikeVitePluginOptions, userRootDir);
222
- setCliAndApiOptions(pageConfigGlobal, configDefinitionsResolved);
223
+ setCliAndApiOptions(pageConfigGlobal, pageConfigs, configDefinitionsResolved);
224
+ warnEarlySettingsInConfigFile(pageConfigGlobal);
223
225
  const globalConfigPublic = resolveGlobalConfig(pageConfigGlobal, pageConfigs);
224
226
  const prerenderContext = await resolvePrerenderContext({
225
227
  config: globalConfigPublic.config,
@@ -283,7 +285,7 @@ async function resolveConfigDefinitions(plusFilesByLocationId, userRootDir, esbu
283
285
  configNamesKnownAll,
284
286
  configNamesKnownGlobal,
285
287
  };
286
- assertKnownConfigs(configDefinitionsResolved);
288
+ warnUnknownConfigs(configDefinitionsResolved);
287
289
  return configDefinitionsResolved;
288
290
  }
289
291
  // Load value files (with `env.config===true`) of *custom* configs.
@@ -464,29 +466,47 @@ function temp_interopVikeVitePlugin(pageConfigGlobal, vikeVitePluginOptions, use
464
466
  }, pageConfigGlobal.configDefinitions));
465
467
  });
466
468
  }
467
- function setCliAndApiOptions(pageConfigGlobal, configDefinitionsResolved) {
469
+ function setCliAndApiOptions(pageConfigGlobal, pageConfigs, configDefinitionsResolved) {
468
470
  // Vike API — passed options [lowest precedence]
469
471
  const vikeApiOperation = getVikeApiOperation();
470
472
  if (vikeApiOperation?.options.vikeConfig) {
471
- addSources(vikeApiOperation.options.vikeConfig, { definedBy: 'api', operation: vikeApiOperation.operation }, false);
473
+ addSources(vikeApiOperation.options.vikeConfig, {
474
+ definedBy: 'api',
475
+ operation: vikeApiOperation.operation,
476
+ });
472
477
  }
473
478
  const { configFromCliOptions, configFromEnvVar } = getVikeConfigFromCliOrEnv();
474
479
  // Vike CLI options
475
480
  if (configFromCliOptions) {
476
- addSources(configFromCliOptions, { definedBy: 'cli' }, true);
481
+ addSources(configFromCliOptions, { definedBy: 'cli' });
477
482
  }
478
483
  // VIKE_CONFIG [highest precedence]
479
484
  if (configFromEnvVar) {
480
- addSources(configFromEnvVar, { definedBy: 'env' }, false);
485
+ addSources(configFromEnvVar, { definedBy: 'env' });
481
486
  }
482
487
  return;
483
- function addSources(configValues, definedBy, exitOnError) {
488
+ function addSources(configValues, definedBy) {
484
489
  Object.entries(configValues).forEach(([configName, value]) => {
485
490
  var _a;
486
491
  const sourceName = `The ${getDefinedByString(definedBy, configName)}`;
487
- assertKnownConfig(configName, configDefinitionsResolved.configNamesKnownGlobal, configDefinitionsResolved, '/', false, sourceName, exitOnError);
488
- const sources = ((_a = pageConfigGlobal.configValueSources)[configName] ?? (_a[configName] = []));
489
- sources.unshift(getSourceNonConfigFile(configName, value, definedBy, pageConfigGlobal.configDefinitions));
492
+ const isUnknown = isUnknownConfig(configName, configDefinitionsResolved.configNamesKnownAll, configDefinitionsResolved, '/', false, sourceName);
493
+ if (isUnknown)
494
+ return;
495
+ if (configName in pageConfigGlobal.configDefinitions) {
496
+ const sources = ((_a = pageConfigGlobal.configValueSources)[configName] ?? (_a[configName] = []));
497
+ const source = getSourceNonConfigFile(configName, value, definedBy, pageConfigGlobal.configDefinitions);
498
+ sources.unshift(source);
499
+ return;
500
+ }
501
+ // Non-global config: inject into every page config that knows about it (highest precedence)
502
+ pageConfigs.forEach((pageConfig) => {
503
+ var _a;
504
+ if (!(configName in pageConfig.configDefinitions))
505
+ return;
506
+ const sources = ((_a = pageConfig.configValueSources)[configName] ?? (_a[configName] = []));
507
+ const source = getSourceNonConfigFile(configName, value, definedBy, pageConfig.configDefinitions);
508
+ sources.unshift(source);
509
+ });
490
510
  });
491
511
  }
492
512
  }
@@ -518,6 +538,30 @@ function getSourceNonConfigFile(configName, value, definedAt, configDefinitionsG
518
538
  };
519
539
  return source;
520
540
  }
541
+ // Settings that must be resolved early before Vike crawls +config.js files:
542
+ // - They can't be defined inside +config.js files.
543
+ // - They must be set early (via Vike's CLI/API options or VIKE_CONFIG), and read early before Vike's main config resolution.
544
+ const EARLY_SETTINGS = [
545
+ // +root determines where Vike looks for +config.js files (so it can't be defined inside +config.js itself)
546
+ 'root',
547
+ // +mode affects which vite.config.js environment is loaded
548
+ 'mode',
549
+ ];
550
+ function warnEarlySettingsInConfigFile(pageConfigGlobal) {
551
+ for (const configName of EARLY_SETTINGS) {
552
+ const sources = pageConfigGlobal.configValueSources[configName];
553
+ if (!sources)
554
+ continue;
555
+ for (const source of sources) {
556
+ if (!source.plusFile) {
557
+ // `plusFile === null` => source comes from Vike CLI argument, Vike API option, or VIKE_CONFIG
558
+ continue;
559
+ }
560
+ const configDefinedAt = getConfigDefinedAt('Config', configName, source.definedAt);
561
+ assertWarning(false, `${configDefinedAt} has no effect: it can't be set from a ${pc.cyan('+')} file — see ${pc.underline(`https://vike.dev/${configName}`)}`, { onlyOnce: true });
562
+ }
563
+ }
564
+ }
521
565
  function sortConfigValueSources(configValueSources, locationIdPage) {
522
566
  Object.entries(configValueSources).forEach(([configName, sources]) => {
523
567
  sources
@@ -973,29 +1017,32 @@ function getComputed(pageConfig) {
973
1017
  });
974
1018
  return configValuesComputed;
975
1019
  }
976
- // Show error message upon unknown config
977
- function assertKnownConfigs(configDefinitionsResolved) {
1020
+ function warnUnknownConfigs(configDefinitionsResolved) {
978
1021
  objectEntries(configDefinitionsResolved.configDefinitionsLocal).forEach(([_locationId, { configNamesKnownLocal, plusFiles }]) => {
979
1022
  plusFiles.forEach((plusFile) => {
980
1023
  const configNames = getConfigNamesSetByPlusFile(plusFile);
981
1024
  configNames.forEach((configName) => {
982
1025
  const { locationId } = plusFile;
983
1026
  const sourceName = plusFile.filePath.filePathToShowToUser;
984
- assertKnownConfig(configName, configNamesKnownLocal, configDefinitionsResolved, locationId, true, sourceName, false);
1027
+ isUnknownConfig(configName, configNamesKnownLocal, configDefinitionsResolved, locationId, true, sourceName);
985
1028
  });
986
1029
  });
987
1030
  });
988
1031
  }
989
- function assertKnownConfig(configName, configNamesKnownRelevant, configDefinitionsResolved, locationId, isPlusFile, sourceName, exitOnError) {
1032
+ function isUnknownConfig(configName, configNamesKnownRelevant, configDefinitionsResolved, locationId, isPlusFile, sourceName) {
990
1033
  const { configNamesKnownAll } = configDefinitionsResolved;
991
1034
  if (configNamesKnownRelevant.includes(configName)) {
992
1035
  assert(configNamesKnownAll.includes(configName));
993
- return;
1036
+ return false;
994
1037
  }
995
1038
  const configNameColored = pc.cyan(configName);
1039
+ const warn = (msg) => {
1040
+ assertWarning(false, msg, { onlyOnce: true });
1041
+ return true;
1042
+ };
996
1043
  // Inheritance issue: config is known but isn't defined at `locationId`
997
1044
  if (configNamesKnownAll.includes(configName)) {
998
- assertUsage(false, `${sourceName} sets the value of the config ${configNameColored} which is a custom config that is defined with ${pc.underline('https://vike.dev/meta')} at a path that doesn't apply to ${locationId} — see ${pc.underline('https://vike.dev/config#inheritance')}`, { exitOnError });
1045
+ return warn(`${sourceName} sets the value of the config ${configNameColored} which is a custom config that is defined with ${pc.underline('https://vike.dev/meta')} at a path that doesn't apply to ${locationId} — see ${pc.underline('https://vike.dev/config#inheritance')}`);
999
1046
  }
1000
1047
  const errMsg = isPlusFile
1001
1048
  ? `${sourceName} sets an unknown config ${configNameColored}`
@@ -1018,7 +1065,7 @@ function assertKnownConfig(configName, configNamesKnownRelevant, configDefinitio
1018
1065
  if (configName in knownVikeExntensionConfigs) {
1019
1066
  const requiredVikeExtension = joinEnglish(knownVikeExntensionConfigs[configName].map((e) => pc.bold(e)), 'or');
1020
1067
  const errMsgEnhanced = `${errMsg}. If you want to use the configuration ${configNameColored} documented at ${pc.underline(`https://vike.dev/${configName}`)} then make sure to install ${requiredVikeExtension}. (Alternatively, you can define ${configNameColored} yourself by using ${pc.cyan('meta')}, see ${pc.underline('https://vike.dev/meta')} for more information.)`;
1021
- assertUsage(false, errMsgEnhanced, { exitOnError });
1068
+ return warn(errMsgEnhanced);
1022
1069
  }
1023
1070
  }
1024
1071
  // Similarity hint
@@ -1035,9 +1082,9 @@ function assertKnownConfig(configName, configNamesKnownRelevant, configDefinitio
1035
1082
  if (configName === 'page') {
1036
1083
  errMsgEnhanced += ` (The name of the config ${pc.cyan('Page')} starts with a capital letter ${pc.cyan('P')} because it defines a UI component: a ubiquitous JavaScript convention is that the name of UI components start with a capital letter.)`;
1037
1084
  }
1038
- assertUsage(false, errMsgEnhanced, { exitOnError });
1085
+ return warn(errMsgEnhanced);
1039
1086
  }
1040
- assertUsage(false, errMsg, { exitOnError });
1087
+ return warn(errMsg);
1041
1088
  }
1042
1089
  function determineRouteFilesystem(locationId, configValueSources) {
1043
1090
  const configName = 'filesystemRoutingRoot';
@@ -489,6 +489,12 @@ type ConfigBuiltIn = {
489
489
  * https://vike.dev/force
490
490
  */
491
491
  force?: boolean;
492
+ /**
493
+ * The root directory of your project.
494
+ *
495
+ * https://vike.dev/root
496
+ */
497
+ root?: string;
492
498
  /**
493
499
  * Content Security Policy (CSP).
494
500
  *
@@ -8,6 +8,5 @@ import type { Fetchable, ServerOptions } from '@universal-deploy/store';
8
8
  interface Server extends Fetchable {
9
9
  prod?: Omit<ServerOptions, 'fetch'> & {
10
10
  static?: boolean | string;
11
- entry?: string;
12
11
  };
13
12
  }
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.259-commit-85c5e84";
1
+ export declare const PROJECT_VERSION: "0.4.259-commit-dcc116b";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.259-commit-85c5e84';
2
+ export const PROJECT_VERSION = '0.4.259-commit-dcc116b';
@@ -3,6 +3,7 @@ export { assertUsage };
3
3
  export { assertWarning };
4
4
  export { assertInfo };
5
5
  export { getProjectError };
6
+ export { getDebugInfoStr };
6
7
  export { isVikeBug };
7
8
  export { setAssertOnBeforeLog };
8
9
  export { setAssertOnBeforeErr };
@@ -10,6 +11,7 @@ export { setAssertAlwaysShowStackTrace };
10
11
  export { setAssertAddAssertTagsDev };
11
12
  import type { AddAssertTagsDev } from '../node/vite/shared/loggerDev.js';
12
13
  declare function assert(condition: unknown, debugInfo?: unknown): asserts condition;
14
+ declare function getDebugInfoStr(debugInfo: unknown): string | null;
13
15
  declare function assertUsage(condition: unknown, errMsg: string, { showStackTrace, exitOnError }?: {
14
16
  showStackTrace?: true;
15
17
  exitOnError?: boolean;
@@ -3,6 +3,7 @@ export { assertUsage };
3
3
  export { assertWarning };
4
4
  export { assertInfo };
5
5
  export { getProjectError };
6
+ export { getDebugInfoStr };
6
7
  export { isVikeBug };
7
8
  export { setAssertOnBeforeLog };
8
9
  export { setAssertOnBeforeErr };
@@ -24,17 +25,10 @@ const tagTypeBug = 'Bug';
24
25
  function assert(condition, debugInfo) {
25
26
  if (condition)
26
27
  return;
27
- const debugStr = (() => {
28
- if (!debugInfo) {
29
- return null;
30
- }
31
- const debugInfoSerialized = typeof debugInfo === 'string' ? debugInfo : JSON.stringify(debugInfo);
32
- return pc.dim(`Debug for maintainers (you can ignore this): ${debugInfoSerialized}`);
33
- })();
34
28
  const link = pc.underline('https://github.com/vikejs/vike/issues/new?template=bug.yml');
35
29
  let errMsg = [
36
30
  `You stumbled upon a Vike bug. Go to ${link} and copy-paste this error. A maintainer will fix the bug (usually within 24 hours).`,
37
- debugStr,
31
+ getDebugInfoStr(debugInfo),
38
32
  ]
39
33
  .filter(Boolean)
40
34
  .join(' ');
@@ -44,6 +38,12 @@ function assert(condition, debugInfo) {
44
38
  globalObject.onBeforeErr?.(internalError);
45
39
  throw internalError;
46
40
  }
41
+ function getDebugInfoStr(debugInfo) {
42
+ if (!debugInfo)
43
+ return null;
44
+ const debugInfoSerialized = typeof debugInfo === 'string' ? debugInfo : JSON.stringify(debugInfo);
45
+ return pc.dim(`Debug for maintainers (you can ignore this): ${debugInfoSerialized}`);
46
+ }
47
47
  function assertUsage(condition, errMsg, { showStackTrace, exitOnError } = {}) {
48
48
  if (condition)
49
49
  return;
@@ -36,7 +36,7 @@ function createRpcClient() {
36
36
  const hot = import.meta.hot;
37
37
  assert(hot);
38
38
  const callId = getRandomId();
39
- const { promise, resolve } = genPromise({ timeout: 3 * 1000 });
39
+ const { promise, resolve } = genPromise({ timeout: 10 * 1000 });
40
40
  listeners.push({
41
41
  callId,
42
42
  cb: (functionReturn) => {
@@ -1 +1 @@
1
- export declare function pick<Obj extends object, Keys extends keyof Obj>(obj: Obj, keys: Keys[]): Pick<Obj, Keys>;
1
+ export declare function pick<Obj extends object, Keys extends keyof Obj>(obj: Obj, keys: readonly Keys[]): Pick<Obj, Keys>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.259-commit-85c5e84",
3
+ "version": "0.4.259-commit-dcc116b",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -146,7 +146,7 @@
146
146
  "semver": "^7.8.1",
147
147
  "sirv": "^3.0.2",
148
148
  "source-map-support": "^0.5.0",
149
- "tinyglobby": "^0.2.16",
149
+ "tinyglobby": "^0.2.17",
150
150
  "vite": ">=6.3.0",
151
151
  "vite-plugin-wrapper": "^0.1.0"
152
152
  },