vike 0.4.221 → 0.4.222-commit-207e079

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 (84) hide show
  1. package/dist/cjs/node/api/prepareViteApiCall.js +18 -16
  2. package/dist/cjs/node/plugin/index.js +1 -1
  3. package/dist/cjs/node/plugin/plugins/baseUrls.js +6 -1
  4. package/dist/cjs/node/plugin/plugins/buildConfig/fixServerAssets.js +8 -10
  5. package/dist/cjs/node/plugin/plugins/buildConfig.js +0 -1
  6. package/dist/cjs/node/plugin/plugins/commonConfig.js +4 -1
  7. package/dist/cjs/node/plugin/plugins/importUserCode/index.js +73 -39
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +64 -14
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +0 -5
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/getPlusFilesAll.js +2 -40
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +1 -1
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +6 -3
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +49 -18
  14. package/dist/cjs/node/runtime/globalContext.js +24 -8
  15. package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +3 -3
  16. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -4
  17. package/dist/cjs/node/runtime/renderPage.js +4 -8
  18. package/dist/cjs/node/runtime-dev/createDevMiddleware.js +3 -3
  19. package/dist/cjs/node/shared/resolveBase.js +0 -13
  20. package/dist/cjs/shared/getPageConfigsRuntime.js +10 -1
  21. package/dist/cjs/shared/page-configs/getPageConfigUserFriendly.js +4 -2
  22. package/dist/cjs/shared/route/loadPageRoutes.js +1 -1
  23. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  24. package/dist/cjs/utils/assertSingleInstance.js +1 -1
  25. package/dist/cjs/utils/debug.js +9 -6
  26. package/dist/esm/client/client-routing-runtime/prefetch.js +1 -1
  27. package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +5 -0
  28. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +9 -2
  29. package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +1 -0
  30. package/dist/esm/client/server-routing-runtime/getPageContext.js +4 -3
  31. package/dist/esm/client/shared/loadUserFilesClientSide.d.ts +3 -2
  32. package/dist/esm/client/shared/loadUserFilesClientSide.js +2 -2
  33. package/dist/esm/node/api/prepareViteApiCall.d.ts +2 -2
  34. package/dist/esm/node/api/prepareViteApiCall.js +18 -16
  35. package/dist/esm/node/plugin/index.d.ts +4 -1
  36. package/dist/esm/node/plugin/index.js +1 -1
  37. package/dist/esm/node/plugin/plugins/baseUrls.js +6 -1
  38. package/dist/esm/node/plugin/plugins/buildConfig/fixServerAssets.d.ts +0 -2
  39. package/dist/esm/node/plugin/plugins/buildConfig/fixServerAssets.js +8 -10
  40. package/dist/esm/node/plugin/plugins/buildConfig.js +1 -2
  41. package/dist/esm/node/plugin/plugins/commonConfig.d.ts +1 -0
  42. package/dist/esm/node/plugin/plugins/commonConfig.js +4 -1
  43. package/dist/esm/node/plugin/plugins/importUserCode/index.js +73 -39
  44. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +4 -0
  45. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +65 -15
  46. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +0 -3
  47. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +0 -5
  48. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/getPlusFilesAll.d.ts +0 -2
  49. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/getPlusFilesAll.js +2 -37
  50. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +1 -1
  51. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.d.ts +1 -1
  52. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +6 -3
  53. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +3 -2
  54. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +50 -19
  55. package/dist/esm/node/runtime/globalContext.d.ts +10 -7
  56. package/dist/esm/node/runtime/globalContext.js +24 -8
  57. package/dist/esm/node/runtime/html/injectAssets/getViteDevScript.d.ts +2 -2
  58. package/dist/esm/node/runtime/html/injectAssets.d.ts +2 -2
  59. package/dist/esm/node/runtime/renderPage/analyzePage.d.ts +2 -2
  60. package/dist/esm/node/runtime/renderPage/getPageAssets.d.ts +2 -2
  61. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.d.ts +2 -2
  62. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.d.ts +2 -2
  63. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +3 -3
  64. package/dist/esm/node/runtime/renderPage/log404/index.d.ts +2 -2
  65. package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.d.ts +2 -2
  66. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +8 -8
  67. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -4
  68. package/dist/esm/node/runtime/renderPage.js +4 -8
  69. package/dist/esm/node/runtime-dev/createDevMiddleware.js +3 -3
  70. package/dist/esm/node/shared/resolveBase.d.ts +1 -9
  71. package/dist/esm/node/shared/resolveBase.js +0 -13
  72. package/dist/esm/shared/getPageConfigsRuntime.d.ts +2 -1
  73. package/dist/esm/shared/getPageConfigsRuntime.js +10 -1
  74. package/dist/esm/shared/page-configs/getPageConfigUserFriendly.d.ts +8 -2
  75. package/dist/esm/shared/page-configs/getPageConfigUserFriendly.js +4 -2
  76. package/dist/esm/shared/route/loadPageRoutes.js +1 -1
  77. package/dist/esm/shared/types.d.ts +9 -0
  78. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  79. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  80. package/dist/esm/utils/assertSingleInstance.js +1 -1
  81. package/dist/esm/utils/debug.d.ts +1 -1
  82. package/dist/esm/utils/debug.js +9 -6
  83. package/dist/esm/utils/projectInfo.d.ts +1 -1
  84. package/package.json +1 -1
@@ -6,7 +6,7 @@ import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
6
6
  import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
7
7
  import { objectAssign } from '../server-routing-runtime/utils.js';
8
8
  const stamp = '__whileFetchingAssets';
9
- async function loadUserFilesClientSide(pageId, pageFilesAll, pageConfigs) {
9
+ async function loadUserFilesClientSide(pageId, pageFilesAll, pageConfigs, pageConfigGlobal) {
10
10
  const pageFilesClientSide = getPageFilesClientSide(pageFilesAll, pageId);
11
11
  const pageConfig = findPageConfig(pageConfigs, pageId);
12
12
  let pageConfigLoaded;
@@ -30,7 +30,7 @@ async function loadUserFilesClientSide(pageId, pageFilesAll, pageConfigs) {
30
30
  }
31
31
  throw err;
32
32
  }
33
- const pageContextExports = getPageConfigUserFriendlyOld(pageFilesClientSide, pageConfigLoaded);
33
+ const pageContextExports = getPageConfigUserFriendlyOld(pageFilesClientSide, pageConfigLoaded, pageConfigGlobal);
34
34
  const pageContextAddendum = {};
35
35
  objectAssign(pageContextAddendum, pageContextExports);
36
36
  objectAssign(pageContextAddendum, { _pageFilesLoaded: pageFilesClientSide });
@@ -5,10 +5,10 @@ export { normalizeViteRoot };
5
5
  import type { InlineConfig, ResolvedConfig } from 'vite';
6
6
  import type { Operation } from './types.js';
7
7
  import { type VikeConfigObject } from '../plugin/plugins/importUserCode/v1-design/getVikeConfig.js';
8
- declare function prepareViteApiCall(viteConfig: InlineConfig | undefined, operation: Operation): Promise<{
8
+ declare function prepareViteApiCall(viteConfigFromOptions: InlineConfig | undefined, operation: Operation): Promise<{
9
9
  vikeConfig: VikeConfigObject;
10
10
  viteConfigEnhanced: InlineConfig | undefined;
11
11
  }>;
12
- declare function getViteRoot(operation: 'build' | 'dev' | 'preview' | 'prerender'): Promise<string>;
12
+ declare function getViteRoot(operation: Operation): Promise<string>;
13
13
  declare function normalizeViteRoot(root: string): string;
14
14
  declare function assertViteRoot(root: string, config: ResolvedConfig): void;
@@ -11,18 +11,18 @@ import { assert, assertUsage, getGlobalObject, isObject, toPosixPath } from './u
11
11
  import pc from '@brillout/picocolors';
12
12
  import { clearGlobalContext } from '../runtime/globalContext.js';
13
13
  const globalObject = getGlobalObject('prepareViteApiCall.ts', {});
14
- async function prepareViteApiCall(viteConfig, operation) {
14
+ async function prepareViteApiCall(viteConfigFromOptions, operation) {
15
15
  clear();
16
16
  setContextApiOperation(operation);
17
- return enhanceViteConfig(viteConfig, operation);
17
+ return enhanceViteConfig(viteConfigFromOptions, operation);
18
18
  }
19
19
  // For subsequent API calls, e.g. calling prerender() after build()
20
20
  function clear() {
21
21
  clearContextApiOperation();
22
22
  clearGlobalContext();
23
23
  }
24
- async function enhanceViteConfig(viteConfig, operation) {
25
- const viteInfo = await getInfoFromVite(viteConfig, operation);
24
+ async function enhanceViteConfig(viteConfigFromOptions, operation) {
25
+ const viteInfo = await getInfoFromVite(viteConfigFromOptions, operation);
26
26
  await assertViteRoot2(viteInfo.root, viteInfo.viteConfigEnhanced, operation);
27
27
  const vikeConfig = await getVikeConfig2(viteInfo.root, operation === 'dev', viteInfo.vikeVitePluginOptions);
28
28
  const viteConfigEnhanced = addViteSettingsSetByVikeConfig(viteInfo.viteConfigEnhanced, vikeConfig);
@@ -38,6 +38,7 @@ function addViteSettingsSetByVikeConfig(viteConfigEnhanced, vikeConfig) {
38
38
  viteConfigs.values.forEach((v) => {
39
39
  assertUsage(isObject(v.value), `${v.definedAt} should be an object`);
40
40
  viteConfigEnhanced = mergeConfig(viteConfigEnhanced ?? {}, v.value);
41
+ assertUsage(!findVikeVitePlugin(v.value), "Using the +vite setting to add Vike's Vite plugin is forbidden");
41
42
  });
42
43
  return viteConfigEnhanced;
43
44
  }
@@ -47,13 +48,14 @@ async function getViteRoot(operation) {
47
48
  assert(globalObject.root);
48
49
  return globalObject.root;
49
50
  }
50
- async function getInfoFromVite(viteConfig, operation) {
51
- const viteConfigFromFile = await loadViteConfigFile(viteConfig, operation);
52
- const root = normalizeViteRoot(viteConfigFromFile?.root ?? viteConfig?.root ?? process.cwd());
51
+ async function getInfoFromVite(viteConfigFromOptions, operation) {
52
+ const viteConfigFromUserViteFile = await loadViteConfigFile(viteConfigFromOptions, operation);
53
+ const root = normalizeViteRoot(viteConfigFromUserViteFile?.root ?? viteConfigFromOptions?.root ?? process.cwd());
53
54
  globalObject.root = root;
54
55
  let vikeVitePluginOptions;
55
- let viteConfigEnhanced = viteConfig;
56
- const found = findVikeVitePlugin([...(viteConfig?.plugins ?? []), ...(viteConfigFromFile?.plugins ?? [])]);
56
+ let viteConfigEnhanced = viteConfigFromOptions;
57
+ // If Vike's Vite plugin is found in both viteConfigFromOptions and viteConfigFromUserViteFile then Vike will later throw an error
58
+ const found = findVikeVitePlugin(viteConfigFromOptions) || findVikeVitePlugin(viteConfigFromUserViteFile);
57
59
  if (found) {
58
60
  vikeVitePluginOptions = found.vikeVitePluginOptions;
59
61
  }
@@ -62,20 +64,20 @@ async function getInfoFromVite(viteConfig, operation) {
62
64
  // Using a dynamic import because the script calling the Vike API may not live in the same place as vite.config.js, thus vike/plugin may resolved to two different node_modules/vike directories.
63
65
  const { plugin: vikePlugin } = await import('../plugin/index.js');
64
66
  viteConfigEnhanced = {
65
- ...viteConfig,
66
- plugins: [...(viteConfig?.plugins ?? []), vikePlugin()]
67
+ ...viteConfigFromOptions,
68
+ plugins: [...(viteConfigFromOptions?.plugins ?? []), vikePlugin()]
67
69
  };
68
- const res = findVikeVitePlugin(viteConfigEnhanced.plugins);
70
+ const res = findVikeVitePlugin(viteConfigEnhanced);
69
71
  assert(res);
70
72
  vikeVitePluginOptions = res.vikeVitePluginOptions;
71
73
  }
72
74
  assert(vikeVitePluginOptions);
73
75
  return { root, vikeVitePluginOptions, viteConfigEnhanced };
74
76
  }
75
- function findVikeVitePlugin(plugins) {
77
+ function findVikeVitePlugin(viteConfig) {
76
78
  let vikeVitePluginOptions;
77
79
  let vikeVitePuginFound = false;
78
- plugins.forEach((p) => {
80
+ viteConfig?.plugins?.forEach((p) => {
79
81
  if (p && '__vikeVitePluginOptions' in p) {
80
82
  vikeVitePuginFound = true;
81
83
  const options = p.__vikeVitePluginOptions;
@@ -88,8 +90,8 @@ function findVikeVitePlugin(plugins) {
88
90
  return { vikeVitePluginOptions };
89
91
  }
90
92
  // Copied from https://github.com/vitejs/vite/blob/4f5845a3182fc950eb9cd76d7161698383113b18/packages/vite/src/node/config.ts#L961-L1005
91
- async function loadViteConfigFile(viteConfig, operation) {
92
- const [inlineConfig, command, defaultMode, _defaultNodeEnv, isPreview] = getResolveConfigArgs(viteConfig, operation);
93
+ async function loadViteConfigFile(viteConfigFromOptions, operation) {
94
+ const [inlineConfig, command, defaultMode, _defaultNodeEnv, isPreview] = getResolveConfigArgs(viteConfigFromOptions, operation);
93
95
  let config = inlineConfig;
94
96
  let mode = inlineConfig.mode || defaultMode;
95
97
  const configEnv = {
@@ -4,7 +4,10 @@ export { plugin as ssr };
4
4
  export type { VikeVitePluginOptions as UserConfig };
5
5
  export type { VikeVitePluginOptions };
6
6
  export { PROJECT_VERSION as version } from './utils.js';
7
- declare function plugin(vikeVitePluginOptions?: VikeVitePluginOptions): any;
7
+ type PluginInterop = Record<string, unknown> & {
8
+ name: string;
9
+ };
10
+ declare function plugin(vikeVitePluginOptions?: VikeVitePluginOptions): PluginInterop[];
8
11
  /** @deprecated Define Vike settings in +config.js instead of vite.config.js */
9
12
  type VikeVitePluginOptions = {
10
13
  /** @deprecated Define Vike settings in +config.js instead of vite.config.js */
@@ -29,7 +29,7 @@ import { workaroundVite6HmrRegression } from './plugins/workaroundVite6HmrRegres
29
29
  import { buildApp } from './plugins/buildApp.js';
30
30
  // We don't call this in ./onLoad.ts to avoid a cyclic dependency with utils.ts
31
31
  setResolveClientEntriesDev(resolveClientEntriesDev);
32
- // Return as `any` to avoid Plugin type mismatches when there are multiple Vite versions installed
32
+ // Return `PluginInterop` instead of `Plugin` to avoid type mismatch upon different Vite versions
33
33
  function plugin(vikeVitePluginOptions = {}) {
34
34
  const plugins = [
35
35
  ...commonConfig(vikeVitePluginOptions),
@@ -1,5 +1,5 @@
1
1
  export { baseUrls };
2
- import { resolveBase, resolveBaseFromResolvedConfig } from '../../shared/resolveBase.js';
2
+ import { resolveBase } from '../../shared/resolveBase.js';
3
3
  import { assert } from '../utils.js';
4
4
  import { getVikeConfig } from './importUserCode/v1-design/getVikeConfig.js';
5
5
  function baseUrls() {
@@ -38,3 +38,8 @@ function baseUrls() {
38
38
  }
39
39
  };
40
40
  }
41
+ function resolveBaseFromResolvedConfig(baseServer, baseAssets, config) {
42
+ let baseViteOriginal = config._baseViteOriginal;
43
+ assert(baseViteOriginal === null || typeof baseViteOriginal == 'string');
44
+ return resolveBase(baseViteOriginal, baseServer, baseAssets);
45
+ }
@@ -2,7 +2,6 @@ export { fixServerAssets };
2
2
  export { fixServerAssets_isEnabled };
3
3
  export { fixServerAssets_assertCssCodeSplit };
4
4
  export { fixServerAssets_assertCssTarget };
5
- export { fixServerAssets_assertCssTarget_populate };
6
5
  import { ViteManifest } from '../../../shared/ViteManifest.js';
7
6
  import { ResolvedConfig } from 'vite';
8
7
  /**
@@ -18,5 +17,4 @@ declare function fixServerAssets(config: ResolvedConfig): Promise<{
18
17
  serverManifestMod: ViteManifest;
19
18
  }>;
20
19
  declare function fixServerAssets_assertCssCodeSplit(config: ResolvedConfig): void;
21
- declare function fixServerAssets_assertCssTarget_populate(config: ResolvedConfig): void;
22
20
  declare function fixServerAssets_assertCssTarget(config: ResolvedConfig): Promise<void>;
@@ -2,7 +2,6 @@ export { fixServerAssets };
2
2
  export { fixServerAssets_isEnabled };
3
3
  export { fixServerAssets_assertCssCodeSplit };
4
4
  export { fixServerAssets_assertCssTarget };
5
- export { fixServerAssets_assertCssTarget_populate };
6
5
  import fs from 'fs/promises';
7
6
  import fs_sync from 'fs';
8
7
  import path from 'path';
@@ -195,17 +194,15 @@ function fixServerAssets_assertCssCodeSplit(config) {
195
194
  assertWarning(config.build.cssCodeSplit, `${pc.cyan('build.cssCodeSplit')} shouldn't be set to ${pc.cyan('false')} (https://github.com/vikejs/vike/issues/1993)`, { onlyOnce: true });
196
195
  }
197
196
  const targets = [];
198
- function fixServerAssets_assertCssTarget_populate(config) {
199
- const isServerSide = viteIsSSR(config);
200
- assert(typeof isServerSide === 'boolean');
201
- assert(config.build.target !== undefined);
202
- targets.push({ global: config.build.target, css: config.build.cssTarget, isServerSide });
203
- }
204
197
  async function fixServerAssets_assertCssTarget(config) {
205
198
  if (!fixServerAssets_isEnabled())
206
199
  return;
207
200
  if (!(await isV1Design(config)))
208
201
  return;
202
+ const isServerSide = viteIsSSR(config);
203
+ assert(typeof isServerSide === 'boolean');
204
+ assert(config.build.target !== undefined);
205
+ targets.push({ global: config.build.target, css: config.build.cssTarget, isServerSide });
209
206
  const targetsServer = targets.filter((t) => t.isServerSide);
210
207
  const targetsClient = targets.filter((t) => !t.isServerSide);
211
208
  targetsClient.forEach((targetClient) => {
@@ -213,9 +210,10 @@ async function fixServerAssets_assertCssTarget(config) {
213
210
  targetsServer.forEach((targetServer) => {
214
211
  const targetCssResolvedServer = resolveCssTarget(targetServer);
215
212
  assertWarning(isEqualStringList(targetCssResolvedClient, targetCssResolvedServer), [
216
- 'The CSS browser target should be the same for both client-side and server-side (https://github.com/vikejs/vike/issues/1815#issuecomment-2507002979) but we got:',
217
- `Client-side: ${pc.cyan(JSON.stringify(targetCssResolvedClient))}`,
218
- `Server-side: ${pc.cyan(JSON.stringify(targetCssResolvedServer))}`
213
+ 'The CSS browser target should be the same for both client and server, but we got:',
214
+ `Client: ${pc.cyan(JSON.stringify(targetCssResolvedClient))}`,
215
+ `Server: ${pc.cyan(JSON.stringify(targetCssResolvedServer))}`,
216
+ `Different targets lead to CSS duplication, see ${pc.underline('https://github.com/vikejs/vike/issues/1815#issuecomment-2507002979')} for more information.`
219
217
  ].join('\n'), {
220
218
  showStackTrace: true,
221
219
  onlyOnce: 'different-css-target'
@@ -10,7 +10,7 @@ import { extractAssetsAddQuery } from '../../shared/extractAssetsQuery.js';
10
10
  import { createRequire } from 'module';
11
11
  import fs from 'fs/promises';
12
12
  import path from 'path';
13
- import { fixServerAssets, fixServerAssets_assertCssCodeSplit, fixServerAssets_assertCssTarget, fixServerAssets_assertCssTarget_populate, fixServerAssets_isEnabled } from './buildConfig/fixServerAssets.js';
13
+ import { fixServerAssets, fixServerAssets_assertCssCodeSplit, fixServerAssets_assertCssTarget, fixServerAssets_isEnabled } from './buildConfig/fixServerAssets.js';
14
14
  import { set_ASSETS_MANIFEST } from './buildEntry/index.js';
15
15
  import { prependEntriesDir } from '../../shared/prependEntriesDir.js';
16
16
  import { getFilePathResolved } from '../shared/getFilePath.js';
@@ -48,7 +48,6 @@ function buildConfig() {
48
48
  config.build.ssrEmitAssets = true;
49
49
  // Required if `ssrEmitAssets: true`, see https://github.com/vitejs/vite/pull/11430#issuecomment-1454800934
50
50
  config.build.cssMinify = 'esbuild';
51
- fixServerAssets_assertCssTarget_populate(config);
52
51
  fixServerAssets_assertCssCodeSplit(config);
53
52
  }
54
53
  }
@@ -11,6 +11,7 @@ declare module 'vite' {
11
11
  _viteConfigEnhanced?: InlineConfig;
12
12
  vike?: {
13
13
  config: VikeConfigObject['global']['config'];
14
+ pages: VikeConfigObject['pages'];
14
15
  prerenderContext?: PrerenderContextPublic;
15
16
  };
16
17
  }
@@ -30,7 +30,10 @@ function commonConfig(vikeVitePluginOptions) {
30
30
  _isDev: isDev,
31
31
  _root: root,
32
32
  _vikeVitePluginOptions: vikeVitePluginOptions,
33
- vike: { config: vikeConfig.global.config },
33
+ vike: {
34
+ pages: vikeConfig.pages,
35
+ config: vikeConfig.global.config
36
+ },
34
37
  // TODO/v1-release: remove https://github.com/vikejs/vike/issues/2122
35
38
  configVikePromise: Promise.resolve({
36
39
  prerender: isPrerenderEnabled(vikeConfig)
@@ -10,8 +10,8 @@ import { vikeConfigDependencies, reloadVikeConfig, isV1Design, getVikeConfig } f
10
10
  import pc from '@brillout/picocolors';
11
11
  import { logConfigInfo } from '../../shared/loggerNotProd.js';
12
12
  import { getModuleFilePathAbsolute } from '../../shared/getFilePath.js';
13
- import { getPlusFileValueConfigName } from './v1-design/getVikeConfig/getPlusFilesAll.js';
14
13
  import { updateUserFiles } from '../../../runtime/globalContext.js';
14
+ import { isPlusFile } from './v1-design/getVikeConfig/crawlPlusFiles.js';
15
15
  function importUserCode() {
16
16
  let config;
17
17
  let vikeConfig;
@@ -68,50 +68,55 @@ function handleFileAddRemove(server, config) {
68
68
  return;
69
69
  function listener(file, isRemove) {
70
70
  file = normalizePath(file);
71
- const isVikeConfig = isVikeConfigModule(file) || isVikeConfigFile(file);
72
- if (isVikeConfig) {
73
- const virtualModules = getVirtualModules(server);
74
- virtualModules.forEach((mod) => {
75
- server.moduleGraph.invalidateModule(mod);
76
- });
71
+ if (isPlusFile(file) || isVikeConfigDependency(file, server.moduleGraph)?.modifiesVikeVirtualFiles) {
72
+ invalidateVikeVirtualFiles(server);
77
73
  reloadConfig(file, config, isRemove ? 'removed' : 'created');
78
74
  }
79
75
  }
80
76
  }
77
+ function invalidateVikeVirtualFiles(server) {
78
+ const vikeVirtualFiles = getVikeVirtualFiles(server);
79
+ vikeVirtualFiles.forEach((mod) => {
80
+ server.moduleGraph.invalidateModule(mod);
81
+ });
82
+ }
81
83
  function handleHotUpdate(ctx, config) {
82
84
  const { file, server } = ctx;
83
- const isVikeConfig = isVikeConfigModule(file);
84
- const isViteModule = ctx.modules.length > 0;
85
- /* Should we show this?
86
- // - Can be useful for server files that aren't processed by Vite.
87
- // - Can be annoying for files that obviously aren't processed by Vite.
88
- if (!isVikeConfig && !isViteModule) {
89
- logViteAny(
90
- `${msg} — ${pc.cyan('no HMR')}, see https://vike.dev/on-demand-compiler`,
91
- 'info',
92
- null,
93
- true
94
- )
95
- return
96
- }
97
- //*/
98
- // It can hide an error it shouldn't hide (because the error isn't shown again), but it's ok since users can reload the page and the error will be shown again (Vite transpilation errors are shown again upon a page reload).
99
- if (!isVikeConfig && isViteModule) {
100
- return;
101
- }
85
+ const isVikeConfig = isVikeConfigDependency(ctx.file, ctx.server.moduleGraph);
102
86
  if (isVikeConfig) {
103
- /* Tailwind breaks this assertion, see https://github.com/vikejs/vike/discussions/1330#discussioncomment-7787238
104
- assert(!isViteModule)
105
- */
106
- reloadConfig(file, config, 'modified');
107
- const virtualModules = getVirtualModules(server);
108
- return virtualModules;
87
+ if (isVikeConfig.modifiesVikeVirtualFiles) {
88
+ /* Tailwind breaks this assertion, see https://github.com/vikejs/vike/discussions/1330#discussioncomment-7787238
89
+ const isViteModule = ctx.modules.length > 0
90
+ assert(!isViteModule)
91
+ */
92
+ // Ensure server.ssrLoadModule() loads fresh Vike virtual files (`reloadConfig()` > `updateUserFiles()` > `server.ssrLoadModule()`)
93
+ invalidateVikeVirtualFiles(server);
94
+ reloadConfig(file, config, 'modified');
95
+ // Triggers a full page reload
96
+ const vikeVirtualFiles = getVikeVirtualFiles(server);
97
+ return vikeVirtualFiles;
98
+ }
99
+ else {
100
+ // Ensure we invalidate `file` *before* server.ssrLoadModule() in updateUserFiles()
101
+ // Vite already invalidates it, but possibly *after* handleHotUpdate() and thus after server.ssrLoadModule()
102
+ ctx.modules.forEach((mod) => server.moduleGraph.invalidateModule(mod));
103
+ updateUserFiles();
104
+ }
109
105
  }
110
106
  }
111
- function isVikeConfigModule(filePathAbsoluteFilesystem) {
107
+ function isVikeConfigDependency(filePathAbsoluteFilesystem, moduleGraph) {
108
+ // Check config-only files, for example all pages/+config.js dependencies. (There aren't part of Vite's module graph.)
112
109
  assertPosixPath(filePathAbsoluteFilesystem);
113
110
  vikeConfigDependencies.forEach((f) => assertPosixPath(f));
114
- return vikeConfigDependencies.has(filePathAbsoluteFilesystem);
111
+ if (vikeConfigDependencies.has(filePathAbsoluteFilesystem))
112
+ return { modifiesVikeVirtualFiles: true };
113
+ // Check using Vite's module graph, for example all +htmlAttributes dependencies.
114
+ // Alternatively, simply call updateUserFiles() on every handleHotUpdate() call.
115
+ const importers = getImporters(filePathAbsoluteFilesystem, moduleGraph);
116
+ const isPlusValueFileDependency = Array.from(importers).some((importer) => importer.file && isPlusFile(importer.file));
117
+ if (isPlusValueFileDependency)
118
+ return { modifiesVikeVirtualFiles: false };
119
+ return null;
115
120
  }
116
121
  function reloadConfig(filePath, config, op) {
117
122
  {
@@ -122,16 +127,45 @@ function reloadConfig(filePath, config, op) {
122
127
  reloadVikeConfig(config);
123
128
  updateUserFiles();
124
129
  }
125
- function getVirtualModules(server) {
126
- const virtualModules = Array.from(server.moduleGraph.urlToModuleMap.keys())
130
+ function getVikeVirtualFiles(server) {
131
+ const vikeVirtualFiles = Array.from(server.moduleGraph.urlToModuleMap.keys())
127
132
  .filter((url) => isVirtualFileIdPageConfigValuesAll(url) || isVirtualFileIdImportUserCode(url))
128
133
  .map((url) => {
129
134
  const mod = server.moduleGraph.urlToModuleMap.get(url);
130
135
  assert(mod);
131
136
  return mod;
132
137
  });
133
- return virtualModules;
138
+ return vikeVirtualFiles;
139
+ }
140
+ // Get all transitive importers (including the module itself)
141
+ function getImporters(file, moduleGraph) {
142
+ const importers = new Set();
143
+ const mods = moduleGraph.getModulesByFile(file);
144
+ if (!mods)
145
+ return importers;
146
+ for (const mod of mods) {
147
+ getModuleImporters(mod).forEach((importer) => {
148
+ if (importer)
149
+ importers.add(importer);
150
+ });
151
+ }
152
+ return importers;
134
153
  }
135
- function isVikeConfigFile(filePath) {
136
- return !!getPlusFileValueConfigName(filePath);
154
+ function getModuleImporters(mod, seen = new Set()) {
155
+ if (seen.has(mod))
156
+ return new Set();
157
+ seen.add(mod);
158
+ const importers = new Set();
159
+ if (mod.id)
160
+ importers.add(mod);
161
+ // Traverse through the importers (modules that import this module)
162
+ for (const importer of mod.importers) {
163
+ if (importer.id)
164
+ importers.add(importer);
165
+ getModuleImporters(importer, seen).forEach((importerTransitive) => {
166
+ if (importerTransitive)
167
+ importers.add(importerTransitive);
168
+ });
169
+ }
170
+ return importers;
137
171
  }
@@ -1,4 +1,8 @@
1
1
  export { crawlPlusFiles };
2
+ export { isPlusFile };
3
+ export { getPlusFileValueConfigName };
2
4
  declare function crawlPlusFiles(userRootDir: string, outDirAbsoluteFilesystem: null | string): Promise<{
3
5
  filePathAbsoluteUserRootDir: string;
4
6
  }[]>;
7
+ declare function isPlusFile(filePath: string): boolean;
8
+ declare function getPlusFileValueConfigName(filePath: string): string | null;
@@ -1,5 +1,7 @@
1
1
  export { crawlPlusFiles };
2
- import { assertPosixPath, assert, scriptFileExtensions, assertIsSingleModuleInstance, assertIsNotProductionRuntime, isVersionOrAbove, isScriptFile, scriptFileExtensionList } from '../../../../utils.js';
2
+ export { isPlusFile };
3
+ export { getPlusFileValueConfigName };
4
+ import { assertPosixPath, assert, scriptFileExtensions, assertIsSingleModuleInstance, assertIsNotProductionRuntime, isVersionOrAbove, isScriptFile, scriptFileExtensionList, createDebugger, deepEqual, assertUsage } from '../../../../utils.js';
3
5
  import path from 'path';
4
6
  import glob from 'fast-glob';
5
7
  import { exec } from 'child_process';
@@ -7,6 +9,7 @@ import { promisify } from 'util';
7
9
  import { isTemporaryBuildFile } from './transpileAndExecuteFile.js';
8
10
  import { getEnvVarObject } from '../../../../shared/getEnvVarObject.js';
9
11
  const execA = promisify(exec);
12
+ const debug = createDebugger('vike:crawl');
10
13
  assertIsNotProductionRuntime();
11
14
  assertIsSingleModuleInstance('crawlPlusFiles.ts');
12
15
  let gitIsNotUsable = false;
@@ -30,17 +33,16 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem) {
30
33
  //
31
34
  !outDirRelativeFromUserRootDir.startsWith('../')));
32
35
  // Crawl
33
- let files;
34
- const res = !isGitCrawlDisabled() && (await gitLsFiles(userRootDir, outDirRelativeFromUserRootDir));
35
- if (res &&
36
- // Fallback to fast-glob for users that dynamically generate plus files. (Assuming that no plus file is found because of the user's .gitignore list.)
37
- res.length > 0) {
38
- files = res;
39
- // We cannot find files inside symlink directories with `$ git ls-files` => we use fast-glob
40
- }
41
- else {
42
- files = await fastGlob(userRootDir, outDirRelativeFromUserRootDir);
43
- }
36
+ const filesGit = !isGitCrawlDisabled() && (await gitLsFiles(userRootDir, outDirRelativeFromUserRootDir));
37
+ const filesGitNothingFound = !filesGit || filesGit.length === 0;
38
+ const filesGlob = (filesGitNothingFound || debug.isActivated) && (await fastGlob(userRootDir, outDirRelativeFromUserRootDir));
39
+ let files = !filesGitNothingFound
40
+ ? filesGit
41
+ : // Fallback to fast-glob for users that dynamically generate plus files. (Assuming that no plus file is found because of the user's .gitignore list.)
42
+ filesGlob;
43
+ assert(files);
44
+ if (debug.isActivated)
45
+ assert(deepEqual(filesGlob, filesGit), "Git and glob results aren't matching.");
44
46
  // Filter build files
45
47
  files = files.filter((filePath) => !isTemporaryBuildFile(filePath));
46
48
  // Normalize
@@ -49,6 +51,7 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem) {
49
51
  assertPosixPath(filePath);
50
52
  assert(!filePath.startsWith(userRootDir));
51
53
  const filePathAbsoluteUserRootDir = path.posix.join('/', filePath);
54
+ assert(isPlusFile(filePathAbsoluteUserRootDir));
52
55
  return { filePathAbsoluteUserRootDir };
53
56
  });
54
57
  return plusFiles;
@@ -69,7 +72,7 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
69
72
  preserveUTF8,
70
73
  'ls-files',
71
74
  // Performance gain seems negligible: https://github.com/vikejs/vike/pull/1688#issuecomment-2166206648
72
- ...scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
75
+ ...scriptFileExtensionList.map((ext) => `"**/+*.${ext}" "+*.${ext}"`),
73
76
  // Performance gain is non-negligible.
74
77
  // - https://github.com/vikejs/vike/pull/1688#issuecomment-2166206648
75
78
  // - When node_modules/ is untracked the performance gain could be significant?
@@ -96,6 +99,12 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
96
99
  }
97
100
  throw err;
98
101
  }
102
+ if (debug.isActivated) {
103
+ debug('[git] userRootDir:', userRootDir);
104
+ debug('[git] cmd:', cmd);
105
+ debug('[git] result:', filesAll);
106
+ debug('[git] filesDeleted:', filesDeleted);
107
+ }
99
108
  const files = [];
100
109
  for (const filePath of filesAll) {
101
110
  // + file?
@@ -116,14 +125,21 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
116
125
  }
117
126
  // Same as gitLsFiles() but using fast-glob
118
127
  async function fastGlob(userRootDir, outDirRelativeFromUserRootDir) {
119
- const files = await glob(`**/+*.${scriptFileExtensions}`, {
128
+ const pattern = `**/+*.${scriptFileExtensions}`;
129
+ const options = {
120
130
  ignore: getIgnoreAsPatterns(outDirRelativeFromUserRootDir),
121
131
  cwd: userRootDir,
122
132
  dot: false
123
- });
133
+ };
134
+ const files = await glob(pattern, options);
124
135
  // Make build deterministic, in order to get a stable generated hash for dist/client/assets/entries/entry-client-routing.${hash}.js
125
136
  // https://github.com/vikejs/vike/pull/1750
126
137
  files.sort();
138
+ if (debug.isActivated) {
139
+ debug('[glob] pattern:', pattern);
140
+ debug('[glob] options:', options);
141
+ debug('[glob] result:', files);
142
+ }
127
143
  return files;
128
144
  }
129
145
  // Same as getIgnoreAsFilterFn() but as glob pattern
@@ -210,3 +226,37 @@ function isGitCrawlDisabled() {
210
226
  const crawSettings = getEnvVarObject('VIKE_CRAWL');
211
227
  return crawSettings?.git === false;
212
228
  }
229
+ function isPlusFile(filePath) {
230
+ assertPosixPath(filePath);
231
+ if (isTemporaryBuildFile(filePath))
232
+ return false;
233
+ const fileName = filePath.split('/').pop();
234
+ return fileName.startsWith('+');
235
+ }
236
+ function getPlusFileValueConfigName(filePath) {
237
+ if (!isPlusFile(filePath))
238
+ return null;
239
+ const fileName = path.posix.basename(filePath);
240
+ // assertNoUnexpectedPlusSign(filePath, fileName)
241
+ const basename = fileName.split('.')[0];
242
+ assert(basename.startsWith('+'));
243
+ const configName = basename.slice(1);
244
+ assertUsage(configName !== '', `${filePath} Invalid filename ${fileName}`);
245
+ return configName;
246
+ }
247
+ /* https://github.com/vikejs/vike/issues/1407
248
+ function assertNoUnexpectedPlusSign(filePath: string, fileName: string) {
249
+ const dirs = path.posix.dirname(filePath).split('/')
250
+ dirs.forEach((dir, i) => {
251
+ const dirPath = dirs.slice(0, i + 1).join('/')
252
+ assertUsage(
253
+ !dir.includes('+'),
254
+ `Character '+' is a reserved character: remove '+' from the directory name ${dirPath}/`
255
+ )
256
+ })
257
+ assertUsage(
258
+ !fileName.slice(1).includes('+'),
259
+ `Character '+' is only allowed at the beginning of filenames: make sure ${filePath} doesn't contain any '+' in its filename other than its first letter`
260
+ )
261
+ }
262
+ */
@@ -3,7 +3,6 @@ export { getFilesystemRouteDefinedBy };
3
3
  export { isInherited };
4
4
  export { getLocationId };
5
5
  export { sortAfterInheritanceOrder };
6
- export { isGlobalLocation };
7
6
  export { applyFilesystemRoutingRootEffect };
8
7
  export type { LocationId };
9
8
  export { getLogicalPath };
@@ -46,8 +45,6 @@ declare function getFilesystemRouteString(locationId: LocationId): string;
46
45
  * getLogicalPath('/pages/some-page', ['pages']) => '/some-page'
47
46
  */
48
47
  declare function getLogicalPath(locationId: LocationId, ignoredDirs: string[], removeParenthesesDirs?: true): string;
49
- /** Whether configs defined in `locationId` apply in every `locationIds` */
50
- declare function isGlobalLocation(locationId: LocationId, locationIds: LocationId[]): boolean;
51
48
  declare function sortAfterInheritanceOrder(locationId1: LocationId, locationId2: LocationId, locationIdPage: LocationId): -1 | 1 | 0;
52
49
  /** Whether configs defined at `locationId1` also apply at `locationId2` */
53
50
  declare function isInherited(locationId1: LocationId, locationId2: LocationId): boolean;
@@ -3,7 +3,6 @@ export { getFilesystemRouteDefinedBy };
3
3
  export { isInherited };
4
4
  export { getLocationId };
5
5
  export { sortAfterInheritanceOrder };
6
- export { isGlobalLocation };
7
6
  export { applyFilesystemRoutingRootEffect };
8
7
  // For ./filesystemRouting.spec.ts
9
8
  export { getLogicalPath };
@@ -41,10 +40,6 @@ function getLogicalPath(locationId, ignoredDirs, removeParenthesesDirs) {
41
40
  assertIsPath(logicalPath);
42
41
  return logicalPath;
43
42
  }
44
- /** Whether configs defined in `locationId` apply in every `locationIds` */
45
- function isGlobalLocation(locationId, locationIds) {
46
- return locationIds.every((locId) => isInherited(locationId, locId) || locationIsRendererDir(locId));
47
- }
48
43
  function sortAfterInheritanceOrder(locationId1, locationId2, locationIdPage) {
49
44
  assertLocationId(locationId1);
50
45
  assertLocationId(locationId2);
@@ -1,5 +1,4 @@
1
1
  export { getPlusFilesAll };
2
- export { getPlusFileValueConfigName };
3
2
  export type { PlusFileValue };
4
3
  export type { PlusFile };
5
4
  export type { PlusFilesByLocationId };
@@ -36,4 +35,3 @@ type PlusFileValue = PlusFileCommons & {
36
35
  };
37
36
  type PlusFilesByLocationId = Record<LocationId, PlusFile[]>;
38
37
  declare function getPlusFilesAll(userRootDir: string, esbuildCache: EsbuildCache): Promise<PlusFilesByLocationId>;
39
- declare function getPlusFileValueConfigName(filePath: string): string | null;