vike 0.4.247-commit-e331796 → 0.4.247-commit-1250e38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/client/runtime-client-routing/getPageContext.js +1 -0
  2. package/dist/node/api/dev.d.ts +6 -0
  3. package/dist/node/api/dev.js +23 -9
  4. package/dist/node/vite/index.js +2 -2
  5. package/dist/node/vite/plugins/build/pluginModuleBanner.js +6 -5
  6. package/dist/node/vite/plugins/pluginAssertFileEnv.d.ts +3 -0
  7. package/dist/node/vite/plugins/{pluginFileEnv.js → pluginAssertFileEnv.js} +44 -39
  8. package/dist/node/vite/plugins/pluginCommon/assertResolveAlias.js +1 -1
  9. package/dist/node/vite/plugins/pluginCommon.d.ts +1 -1
  10. package/dist/node/vite/plugins/pluginCommon.js +3 -2
  11. package/dist/node/vite/plugins/pluginDev/optimizeDeps.d.ts +15 -0
  12. package/dist/node/vite/plugins/pluginDev/{determineOptimizeDeps.js → optimizeDeps.js} +45 -4
  13. package/dist/node/vite/plugins/pluginDev.d.ts +1 -1
  14. package/dist/node/vite/plugins/pluginDev.js +3 -19
  15. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFilePageEntry.js +1 -1
  16. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +3 -2
  17. package/dist/node/vite/plugins/pluginVirtualFiles.js +11 -9
  18. package/dist/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +8 -0
  19. package/dist/node/vite/shared/resolveVikeConfigInternal.js +5 -4
  20. package/dist/server/__internal/vite.d.ts +1 -0
  21. package/dist/server/__internal/vite.js +1 -0
  22. package/dist/server/runtime/globalContext.d.ts +0 -2
  23. package/dist/server/runtime/globalContext.js +69 -50
  24. package/dist/server/runtime/renderPageServer/execHookServer.js +9 -2
  25. package/dist/server/runtime/renderPageServer.js +6 -9
  26. package/dist/server/utils.d.ts +1 -1
  27. package/dist/server/utils.js +1 -1
  28. package/dist/shared-server-client/assertVirtualFileExports.d.ts +2 -0
  29. package/dist/shared-server-client/assertVirtualFileExports.js +16 -0
  30. package/dist/shared-server-client/createGlobalContextShared.js +44 -40
  31. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.js +2 -0
  32. package/dist/shared-server-client/page-configs/loadAndParseVirtualFilePageEntry.js +9 -5
  33. package/dist/shared-server-node/getFileSuffixes.d.ts +6 -0
  34. package/dist/shared-server-node/getFileSuffixes.js +22 -0
  35. package/dist/shared-server-node/getVikeConfigError.d.ts +9 -0
  36. package/dist/shared-server-node/getVikeConfigError.js +4 -1
  37. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  38. package/dist/utils/PROJECT_VERSION.js +1 -1
  39. package/dist/utils/assertSetup.js +3 -3
  40. package/dist/utils/debug.d.ts +1 -1
  41. package/dist/utils/debug.js +1 -0
  42. package/dist/utils/getBetterError.js +3 -0
  43. package/dist/utils/isNonRunnableDevProcess.d.ts +2 -0
  44. package/dist/utils/{isNonRunnableDev.js → isNonRunnableDevProcess.js} +2 -2
  45. package/package.json +7 -3
  46. package/dist/node/vite/plugins/pluginDev/determineOptimizeDeps.d.ts +0 -3
  47. package/dist/node/vite/plugins/pluginFileEnv.d.ts +0 -3
  48. package/dist/utils/isNonRunnableDev.d.ts +0 -2
@@ -2,6 +2,7 @@ export { getPageContext };
2
2
  export { providePageContext };
3
3
  // TO-DO/eventually: create new setting `+asyncHook: true` that sets the default value of the `asyncHook` parameter below to `true`
4
4
  // TODO/next-release: update vike-{react,vue,solid} usage
5
+ // TODO/next-release: contact Da-Jin about `window.history.state?.vike` https://vike.dev/navigate#history-pushstate
5
6
  import { getPageContext_sync, providePageContext } from '../../shared-server-client/hooks/execHook.js';
6
7
  import { getPageContextClient } from './renderPageClient.js';
7
8
  function getPageContext({ asyncHook } = {}) {
@@ -1,4 +1,5 @@
1
1
  export { dev };
2
+ export { startupLog };
2
3
  import { type ResolvedConfig, type ViteDevServer } from 'vite';
3
4
  import type { ApiOptions } from './types.js';
4
5
  /**
@@ -13,3 +14,8 @@ declare function dev(options?: ApiOptions & {
13
14
  viteConfig: ResolvedConfig;
14
15
  viteVersion: string;
15
16
  }>;
17
+ declare function startupLog(resolvedUrls: ResolvedServerUrls, viteServer: ViteDevServer): Promise<void>;
18
+ interface ResolvedServerUrls {
19
+ local: string[];
20
+ network: string[];
21
+ }
@@ -1,33 +1,47 @@
1
1
  export { dev };
2
+ // TO-DO/eventually: remove if it doesn't end up being used
3
+ export { startupLog };
2
4
  import { prepareViteApiCall } from './prepareViteApiCall.js';
3
- import { createServer, version as viteVersionVike } from 'vite';
4
- import { viteVersionUser } from '../vite/plugins/pluginCommon.js';
5
- import { colorVike, colorVite, PROJECT_VERSION } from './utils.js';
5
+ import { createServer } from 'vite';
6
+ import { assert, assertIsNotProductionRuntime, colorVike, colorVite, PROJECT_VERSION } from './utils.js';
6
7
  import pc from '@brillout/picocolors';
7
8
  import { processStartupLog } from '../vite/shared/loggerVite.js';
9
+ assertIsNotProductionRuntime();
8
10
  /**
9
11
  * Programmatically trigger `$ vike dev`
10
12
  *
11
13
  * https://vike.dev/api#dev
12
14
  */
13
15
  async function dev(options = {}) {
14
- const startTime = performance.now();
15
16
  const { viteConfigFromUserResolved } = await prepareViteApiCall(options, 'dev');
16
17
  const server = await createServer(viteConfigFromUserResolved);
17
- const viteVersion = viteVersionUser ?? viteVersionVike;
18
18
  const viteServer = server;
19
19
  const viteConfig = server.config;
20
+ const viteVersion = viteConfig._viteVersionResolved;
21
+ assert(viteVersion);
20
22
  if (viteServer.httpServer)
21
23
  await viteServer.listen();
22
- if (options.startupLog)
23
- printStartupLog(viteServer, viteConfig, viteVersion, startTime);
24
+ if (options.startupLog) {
25
+ if (viteServer.resolvedUrls) {
26
+ startupLog(viteServer.resolvedUrls, viteServer);
27
+ }
28
+ else {
29
+ // TO-DO/eventually: remove if it doesn't end up being used
30
+ ;
31
+ viteConfig.server.startupLog = (resolvedUrls) => startupLog(resolvedUrls, viteServer);
32
+ }
33
+ }
24
34
  return {
25
35
  viteServer,
26
36
  viteConfig,
27
37
  viteVersion,
28
38
  };
29
39
  }
30
- async function printStartupLog(viteServer, viteConfig, viteVersion, startTime) {
40
+ const startTime = performance.now();
41
+ async function startupLog(resolvedUrls, viteServer) {
42
+ const viteConfig = viteServer.config;
43
+ const viteVersion = viteConfig._viteVersionResolved;
44
+ assert(viteVersion);
31
45
  const startupDurationString = pc.dim(`ready in ${pc.reset(pc.bold(String(Math.ceil(performance.now() - startTime))))} ms`);
32
46
  const sep = pc.dim('·');
33
47
  const firstLine = `\n ${colorVike('Vike')} ${pc.yellow(`v${PROJECT_VERSION}`)} ${sep} ${colorVite('Vite')} ${pc.cyan(`v${viteVersion}`)} ${sep} ${startupDurationString}\n`;
@@ -36,7 +50,7 @@ async function printStartupLog(viteServer, viteConfig, viteVersion, startTime) {
36
50
  const { isCompact } = ret;
37
51
  // We don't call viteServer.printUrls() because Vite throws an error if `resolvedUrls` is missing:
38
52
  // https://github.com/vitejs/vite/blob/df5a30d2690a2ebc4824a79becdcef30538dc602/packages/vite/src/node/server/index.ts#L745
39
- printServerUrls(viteServer.resolvedUrls || { local: ['http://localhost:3000'], network: [] }, viteConfig.server.host);
53
+ printServerUrls(resolvedUrls, viteConfig.server.host);
40
54
  viteServer.bindCLIShortcuts({ print: true });
41
55
  if (!isCompact)
42
56
  console.log();
@@ -17,7 +17,7 @@ import { pluginSetGlobalContext } from './plugins/pluginSetGlobalContext.js';
17
17
  import { pluginCommon } from './plugins/pluginCommon.js';
18
18
  import { pluginBaseUrls } from './plugins/pluginBaseUrls.js';
19
19
  import { pluginReplaceConstantsEnvVars } from './plugins/pluginReplaceConstantsEnvVars.js';
20
- import { pluginFileEnv } from './plugins/pluginFileEnv.js';
20
+ import { pluginAssertFileEnv } from './plugins/pluginAssertFileEnv.js';
21
21
  import { pluginWorkaroundCssModuleHmr } from './plugins/pluginWorkaroundCssModuleHmr.js';
22
22
  import { pluginWorkaroundVite6HmrRegression } from './plugins/pluginWorkaroundVite6HmrRegression.js';
23
23
  import { pluginReplaceConstantsPageContext } from './plugins/pluginReplaceConstantsPageContext.js';
@@ -53,7 +53,7 @@ function plugin(vikeVitePluginOptions = {}) {
53
53
  ...pluginSetGlobalContext(),
54
54
  ...pluginBaseUrls(),
55
55
  ...pluginReplaceConstantsEnvVars(),
56
- ...pluginFileEnv(),
56
+ ...pluginAssertFileEnv(),
57
57
  ...pluginWorkaroundCssModuleHmr(),
58
58
  ...pluginWorkaroundVite6HmrRegression(),
59
59
  ...pluginReplaceConstantsPageContext(),
@@ -1,8 +1,12 @@
1
1
  export { pluginModuleBanner };
2
2
  import { assert, removeVirtualFileIdPrefix } from '../../utils.js';
3
3
  import { getMagicString } from '../../shared/getMagicString.js';
4
- // Rollup's banner feature doesn't work with Vite: https://github.com/vitejs/vite/issues/8412
5
- // But, anyways, we want to prepend the banner at the beginning of each module, not at the beginning of each file (I believe that's what Rollup's banner feature does).
4
+ // Misusing legal comments so that esbuild doesn't remove them.
5
+ // - Legal comments: https://esbuild.github.io/api/#legal-comments
6
+ // - Terser removes legal comments, but I guess users use terser to minify JavaScript so I guess it's a good thing that comment is removed.
7
+ // - Rollup's banner feature doesn't work with Vite: https://github.com/vitejs/vite/issues/8412
8
+ // - But, anyways, we want to prepend the banner at the beginning of each module, not at the beginning of each file (I believe that's what Rollup's banner feature does).
9
+ // - Potential alternative: https://github.com/vitejs/vite/issues/21228#issuecomment-3627899741
6
10
  function pluginModuleBanner() {
7
11
  let config;
8
12
  let isEnabled = false;
@@ -39,9 +43,6 @@ function pluginModuleBanner() {
39
43
  id = id.slice(config.root.length + 1);
40
44
  id = id.replaceAll('*/', '*\\/'); // https://github.com/vikejs/vike/issues/2377
41
45
  const { magicString, getMagicStringResult } = getMagicString(code, id);
42
- // Use legal comment so that esbuild doesn't remove it.
43
- // - Terser still removes the comment, but I guess users use terser to minify JavaScript so I guess it's a good thing that comment is removed.
44
- // - https://esbuild.github.io/api/#legal-comments
45
46
  magicString.prepend(`/*! ${id} [vike:pluginModuleBanner] */\n`);
46
47
  return getMagicStringResult();
47
48
  },
@@ -0,0 +1,3 @@
1
+ export { pluginAssertFileEnv };
2
+ import type { Plugin } from 'vite';
3
+ declare function pluginAssertFileEnv(): Plugin[];
@@ -1,4 +1,4 @@
1
- export { pluginFileEnv };
1
+ export { pluginAssertFileEnv };
2
2
  import { assert, assertUsage, assertWarning, capitalizeFirstLetter, isFilePathAbsolute, joinEnglish, rollupSourceMapRemove, } from '../utils.js';
3
3
  import { extractAssetsRE } from './pluginExtractAssets.js';
4
4
  import { extractExportNamesRE } from './pluginExtractExportNames.js';
@@ -8,26 +8,26 @@ import { getExportNames } from '../shared/parseEsModule.js';
8
8
  import { normalizeId } from '../shared/normalizeId.js';
9
9
  import { isV1Design } from '../shared/resolveVikeConfigInternal.js';
10
10
  import { isViteServerSide, isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
11
- const skipNodeModules = '/node_modules/'; // Only apply `.server.js` and `.client.js` to user files
11
+ import { suffixesAssertFileEnv } from '../../../shared-server-node/getFileSuffixes.js';
12
+ const envS = suffixesAssertFileEnv;
13
+ const skipNodeModules = '/node_modules/'; // Only assert `.server.js`, `.client.js` and `.ssr.js` for user files
12
14
  const filterRolldown = {
13
15
  id: {
14
- include: ['client', 'server'].map((env) => `**/*${getSuffix(env)}*`),
16
+ include: envS.map((env) => `**/*${getSuffix(env)}*`),
15
17
  exclude: [`**${skipNodeModules}**`],
16
18
  },
17
19
  };
18
20
  const filterFunction = (id) => {
19
21
  if (id.includes(skipNodeModules))
20
22
  return false;
21
- if (!id.includes(getSuffix('client')) && !id.includes(getSuffix('server')))
22
- return false;
23
- return true;
23
+ return envS.some((suffix) => id.includes(getSuffix(suffix)));
24
24
  };
25
- function pluginFileEnv() {
25
+ function pluginAssertFileEnv() {
26
26
  let config;
27
27
  let viteDevServer;
28
28
  return [
29
29
  {
30
- name: 'vike:pluginFileEnv',
30
+ name: 'vike:pluginAssertFileEnv',
31
31
  load: {
32
32
  filter: filterRolldown,
33
33
  handler(id, options) {
@@ -68,7 +68,7 @@ function pluginFileEnv() {
68
68
  return;
69
69
  const { importers } = this.getModuleInfo(id);
70
70
  // Throwing a verbose error doesn't waste client-side KBs as dynamic imports are code split.
71
- const errMsg = getErrorMessage(id, isServerSide, importers, false, true);
71
+ const errMsg = getErrMsg(id, isServerSide, importers, false, config, true);
72
72
  // We have to inject empty exports to avoid Rollup complaining about missing exports, see https://gist.github.com/brillout/5ea45776e65bd65100a52ecd7bfda3ff
73
73
  const { exportNames } = await getExportNames(code);
74
74
  return rollupSourceMapRemove([
@@ -111,7 +111,7 @@ function pluginFileEnv() {
111
111
  function assertFileEnv(moduleId, isServerSide, importers, onlyWarn) {
112
112
  if (!isWrongEnv(moduleId, isServerSide))
113
113
  return;
114
- const errMsg = getErrorMessage(moduleId, isServerSide, importers, onlyWarn, false);
114
+ const errMsg = getErrMsg(moduleId, isServerSide, importers, onlyWarn, config, false);
115
115
  if (onlyWarn) {
116
116
  assertWarning(false, errMsg, { onlyOnce: true });
117
117
  }
@@ -119,38 +119,43 @@ function pluginFileEnv() {
119
119
  assertUsage(false, errMsg);
120
120
  }
121
121
  }
122
- function getErrorMessage(moduleId, isServerSide, importers, onlyWarn, noColor) {
123
- const modulePath = getModulePath(moduleId);
124
- const envActual = isServerSide ? 'server' : 'client';
125
- const envExpect = isServerSide ? 'client' : 'server';
126
- let errMsg;
127
- let modulePathPretty = getFilePathToShowToUserModule(modulePath, config);
128
- if (!noColor) {
129
- const suffix = getSuffix(envExpect);
130
- modulePathPretty = modulePathPretty.replaceAll(suffix, pc.bold(suffix));
131
- }
132
- errMsg = `${capitalizeFirstLetter(envExpect)}-only file ${modulePathPretty} (https://vike.dev/file-env) imported on the ${envActual}-side`;
133
- {
134
- const importPaths = importers
135
- .filter((importer) =>
136
- // Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
137
- isFilePathAbsolute(importer))
138
- .map((importer) => getFilePathToShowToUserModule(importer, config))
139
- .map((importPath) => pc.cyan(importPath));
140
- if (importPaths.length > 0) {
141
- errMsg += ` by ${joinEnglish(importPaths, 'and')}`;
142
- }
143
- }
144
- if (onlyWarn) {
145
- errMsg += ". This is potentially a security issue and Vike won't allow you to build your app for production.";
146
- }
147
- return errMsg;
148
- }
149
122
  }
150
123
  function isWrongEnv(moduleId, isServerSide) {
151
124
  const modulePath = getModulePath(moduleId);
152
- const suffixWrong = getSuffix(isServerSide ? 'client' : 'server');
153
- return modulePath.includes(suffixWrong);
125
+ if (isServerSide) {
126
+ // On server-side, .client. is wrong
127
+ return modulePath.includes(getSuffix('client'));
128
+ }
129
+ else {
130
+ // On client-side, both .server. and .ssr. are wrong
131
+ return modulePath.includes(getSuffix('server')) || modulePath.includes(getSuffix('ssr'));
132
+ }
133
+ }
134
+ function getErrMsg(moduleId, isServerSide, importers, onlyWarn, config, noColor) {
135
+ const envActual = isServerSide ? 'server' : 'client';
136
+ const envExpect = isServerSide ? 'client' : 'server';
137
+ const modulePath = getModulePath(moduleId);
138
+ let modulePathPretty = getFilePathToShowToUserModule(modulePath, config);
139
+ if (!noColor) {
140
+ const suffix = modulePath.includes(getSuffix('ssr')) ? getSuffix('ssr') : getSuffix(envExpect);
141
+ modulePathPretty = modulePathPretty.replaceAll(suffix, pc.bold(suffix));
142
+ }
143
+ let errMsg = `${capitalizeFirstLetter(envExpect)}-only file ${modulePathPretty} (https://vike.dev/file-env) imported on the ${envActual}-side`;
144
+ {
145
+ const importPaths = importers
146
+ .filter((importer) =>
147
+ // Can be Vike's virtual module: https://github.com/vikejs/vike/issues/2483
148
+ isFilePathAbsolute(importer))
149
+ .map((importer) => getFilePathToShowToUserModule(importer, config))
150
+ .map((importPath) => pc.cyan(importPath));
151
+ if (importPaths.length > 0) {
152
+ errMsg += ` by ${joinEnglish(importPaths, 'and')}`;
153
+ }
154
+ }
155
+ if (onlyWarn) {
156
+ errMsg += ". This is potentially a security issue and Vike won't allow you to build your app for production.";
157
+ }
158
+ return errMsg;
154
159
  }
155
160
  function skip(id, userRootDir) {
156
161
  assert(filterFunction(id));
@@ -56,7 +56,7 @@ function assertResolveAlias(config) {
56
56
  assertUsage(find !== '', msg);
57
57
  }
58
58
  // Ensure path alias are distinguishable from npm package names, which is needed by:
59
- // - determineOptimizeDeps()
59
+ // - resolveOptimizeDeps()
60
60
  // - extractAssets
61
61
  // - in general: using un-distinguishable path aliases is asking for trouble
62
62
  if (!isPathAliasRecommended(find)) {
@@ -1,5 +1,4 @@
1
1
  export { pluginCommon };
2
- export declare let viteVersionUser: string | null | undefined;
3
2
  import { type InlineConfig, type Plugin } from 'vite';
4
3
  import type { VitePluginServerEntryOptions } from '@brillout/vite-plugin-server-entry/plugin';
5
4
  declare module 'vite' {
@@ -9,6 +8,7 @@ declare module 'vite' {
9
8
  _rootResolvedEarly?: string;
10
9
  _baseViteOriginal?: string;
11
10
  _viteConfigFromUserResolved?: InlineConfig;
11
+ _viteVersionResolved?: string;
12
12
  }
13
13
  }
14
14
  declare global {
@@ -1,5 +1,4 @@
1
1
  export { pluginCommon };
2
- export let viteVersionUser = null;
3
2
  import { assert, assertUsage, assertWarning, hasProp, isDevCheck, isDocker, isExactlyOneTruthy, isObject, isVitest, } from '../utils.js';
4
3
  import { assertRollupInput } from './build/pluginBuildConfig.js';
5
4
  import { installRequireShim_setUserRootDir } from '@brillout/require-shim';
@@ -10,6 +9,7 @@ import { isVikeCliOrApi } from '../../../shared-server-node/api-context.js';
10
9
  import { getVikeConfigInternal, setVikeConfigContext } from '../shared/resolveVikeConfigInternal.js';
11
10
  import { assertViteRoot, getViteRoot, normalizeViteRoot } from '../../api/resolveViteConfigFromUser.js';
12
11
  import { temp_disablePrerenderAutoRun } from '../../prerender/context.js';
12
+ import { version as viteVersionVike } from 'vite';
13
13
  const pluginName = 'vike:pluginCommon';
14
14
  globalThis.__VIKE__IS_PROCESS_SHARED_WITH_VITE = true;
15
15
  function pluginCommon(vikeVitePluginOptions) {
@@ -20,7 +20,7 @@ function pluginCommon(vikeVitePluginOptions) {
20
20
  config: {
21
21
  order: 'pre',
22
22
  async handler(configFromUser, env) {
23
- viteVersionUser = this?.meta?.viteVersion; // is `undefined` on old Vite versions
23
+ const viteVersionUser = this?.meta?.viteVersion; // is `undefined` on old Vite versions
24
24
  const isDev = isDevCheck(env);
25
25
  const isBuild = env.command === 'build';
26
26
  const isPreview = env.isPreview;
@@ -34,6 +34,7 @@ function pluginCommon(vikeVitePluginOptions) {
34
34
  const vikeConfig = await getVikeConfigInternal();
35
35
  return {
36
36
  _isDev: isDev,
37
+ _viteVersionResolved: viteVersionUser || viteVersionVike,
37
38
  _rootResolvedEarly: rootResolvedEarly,
38
39
  // TO-DO/next-major-release: remove https://github.com/vikejs/vike/issues/2122
39
40
  configVikePromise: Promise.resolve({
@@ -0,0 +1,15 @@
1
+ export { optimizeDeps };
2
+ export { resolveOptimizeDeps };
3
+ import type { ResolvedConfig } from 'vite';
4
+ declare const optimizeDeps: {
5
+ readonly optimizeDeps: {
6
+ readonly exclude: ["vike/client", "vike/client/router"];
7
+ readonly include: ["vike > @brillout/json-serializer/parse", "vike > @brillout/json-serializer/stringify", "vike > @brillout/picocolors"];
8
+ };
9
+ readonly ssr: {
10
+ readonly optimizeDeps: {
11
+ readonly exclude: ["@brillout/import", "@brillout/json-serializer", "@brillout/picocolors", "@brillout/vite-plugin-server-entry", "vike"];
12
+ };
13
+ };
14
+ };
15
+ declare function resolveOptimizeDeps(config: ResolvedConfig): Promise<void>;
@@ -1,4 +1,5 @@
1
- export { determineOptimizeDeps };
1
+ export { optimizeDeps };
2
+ export { resolveOptimizeDeps };
2
3
  import { findPageFiles } from '../../shared/findPageFiles.js';
3
4
  import { assert, assertIsImportPathNpmPackage, createDebug, getNpmPackageName, isArray, isFilePathAbsoluteFilesystem, isVirtualFileId, requireResolveOptional, } from '../../utils.js';
4
5
  import { getVikeConfigInternal } from '../../shared/resolveVikeConfigInternal.js';
@@ -7,7 +8,8 @@ import { virtualFileIdGlobalEntryClientCR, virtualFileIdGlobalEntryClientSR, } f
7
8
  import { getFilePathResolved } from '../../shared/getFilePath.js';
8
9
  import { getConfigValueSourcesRelevant } from '../pluginVirtualFiles/getConfigValueSourcesRelevant.js';
9
10
  const debug = createDebug('vike:optimizeDeps');
10
- const WORKAROUND_LATE_DISCOVERY = [
11
+ // Add dependencies that cannot be discovered by Vite during the scanning phase
12
+ const LATE_DISCOVERED = [
11
13
  // Workaround for https://github.com/vitejs/vite-plugin-react/issues/650
12
14
  // - The issue was closed as completed with https://github.com/vitejs/vite/pull/20495 but it doesn't fix the issue and the workaround is still needed.
13
15
  // - TO-DO/eventually: try removing the workaround and see if the CI fails (at test/@cloudflare_vite-plugin/) — maybe the issue will get fixed at some point.
@@ -15,11 +17,47 @@ const WORKAROUND_LATE_DISCOVERY = [
15
17
  // Workaround for https://github.com/vikejs/vike/issues/2823#issuecomment-3514325487
16
18
  '@compiled/react/runtime',
17
19
  ];
18
- async function determineOptimizeDeps(config) {
20
+ const optimizeDeps = {
21
+ optimizeDeps: {
22
+ exclude: [
23
+ // We must exclude Vike's client runtime so it can import virtual modules
24
+ 'vike/client',
25
+ 'vike/client/router',
26
+ ],
27
+ include: [
28
+ // Avoid:
29
+ // ```
30
+ // 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
31
+ // 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
32
+ // ```
33
+ 'vike > @brillout/json-serializer/parse',
34
+ 'vike > @brillout/json-serializer/stringify',
35
+ 'vike > @brillout/picocolors',
36
+ ],
37
+ },
38
+ ssr: {
39
+ optimizeDeps: {
40
+ exclude: [
41
+ '@brillout/import',
42
+ '@brillout/json-serializer',
43
+ '@brillout/picocolors',
44
+ '@brillout/vite-plugin-server-entry',
45
+ 'vike',
46
+ ],
47
+ },
48
+ },
49
+ };
50
+ // Populate optimizeDeps with dynamic entries:
51
+ // - User's + files (i.e. Vike entries)
52
+ // - Late discovered dependencies (if they exist)
53
+ // - Make server environments inherit from ssr.optimizeDeps (it isn't the case by default)
54
+ async function resolveOptimizeDeps(config) {
19
55
  const vikeConfig = await getVikeConfigInternal();
20
56
  const { _pageConfigs: pageConfigs } = vikeConfig;
57
+ // Retrieve user's + files (i.e. Vike entries)
21
58
  const { entriesClient, entriesServer, includeClient, includeServer } = await getPageDeps(config, pageConfigs);
22
- WORKAROUND_LATE_DISCOVERY.forEach((dep) => {
59
+ // Add late discovered dependencies, if they exist
60
+ LATE_DISCOVERED.forEach((dep) => {
23
61
  const userRootDir = config.root;
24
62
  const resolved = requireResolveOptional({ importPath: dep, userRootDir, importerFilePath: null });
25
63
  const resolvedInsideRepo = resolved && resolved.startsWith(userRootDir);
@@ -39,8 +77,10 @@ async function determineOptimizeDeps(config) {
39
77
  includeServer.push(dep);
40
78
  }
41
79
  });
80
+ // Set optimizeDeps (client-side)
42
81
  config.optimizeDeps.include = add(config.optimizeDeps.include, includeClient);
43
82
  config.optimizeDeps.entries = add(config.optimizeDeps.entries, entriesClient);
83
+ // Set optimizeDeps (server-side)
44
84
  for (const envName in config.environments) {
45
85
  const env = config.environments[envName];
46
86
  if (env.consumer === 'server' && env.optimizeDeps.noDiscovery === false) {
@@ -48,6 +88,7 @@ async function determineOptimizeDeps(config) {
48
88
  env.optimizeDeps.entries = add(env.optimizeDeps.entries, entriesServer);
49
89
  }
50
90
  }
91
+ // Debug
51
92
  if (debug.isActivated)
52
93
  debug('optimizeDeps', {
53
94
  'config.optimizeDeps.entries': config.optimizeDeps.entries,
@@ -1,5 +1,5 @@
1
1
  export { pluginDev };
2
2
  export { logDockerHint };
3
- import type { Plugin, ResolvedConfig } from 'vite';
3
+ import { type Plugin, type ResolvedConfig } from 'vite';
4
4
  declare function pluginDev(): Plugin[];
5
5
  declare function logDockerHint(configHost: ResolvedConfig['server']['host']): void;
@@ -1,6 +1,6 @@
1
1
  export { pluginDev };
2
2
  export { logDockerHint };
3
- import { determineOptimizeDeps } from './pluginDev/determineOptimizeDeps.js';
3
+ import { optimizeDeps, resolveOptimizeDeps } from './pluginDev/optimizeDeps.js';
4
4
  import { determineFsAllowList } from './pluginDev/determineFsAllowList.js';
5
5
  import { addSsrMiddleware } from '../shared/addSsrMiddleware.js';
6
6
  import { applyDev, assertWarning, isDocker, isDebugError } from '../utils.js';
@@ -17,30 +17,14 @@ function pluginDev() {
17
17
  handler() {
18
18
  return {
19
19
  appType: 'custom',
20
- optimizeDeps: {
21
- exclude: [
22
- // We must exclude Vike's client runtime so it can import virtual modules
23
- 'vike/client',
24
- 'vike/client/router',
25
- ],
26
- include: [
27
- // Avoid:
28
- // ```
29
- // 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
30
- // 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
31
- // ```
32
- 'vike > @brillout/json-serializer/parse',
33
- 'vike > @brillout/json-serializer/stringify',
34
- 'vike > @brillout/picocolors',
35
- ],
36
- },
20
+ ...optimizeDeps,
37
21
  };
38
22
  },
39
23
  },
40
24
  configResolved: {
41
25
  async handler(config_) {
42
26
  config = config_;
43
- await determineOptimizeDeps(config);
27
+ await resolveOptimizeDeps(config);
44
28
  await determineFsAllowList(config);
45
29
  interceptViteLogs(config);
46
30
  logDockerHint(config.server.host);
@@ -25,7 +25,7 @@ async function generateVirtualFilePageEntry(id, isDev) {
25
25
  assert(pageConfig);
26
26
  }
27
27
  else {
28
- /* This assertion sometimes fail. It happens very seldom and I couldn't reproduce it (https://gist.github.com/brillout/9e212ce829f4d62a912ca163ffa8881a). I suspect some kind of HMR race condition.
28
+ /* This assertion sometimes fail. It happens very seldom and I couldn't reproduce it (https://gist.github.com/brillout/9e212ce829f4d62a912ca163ffa8881a). I suspect some kind of HMR race condition. UPDATE: [December 2024] This just happened at test/@cloudflare_vite-plugin/ — it isn't blocking, reloading the page fixes the issue.
29
29
  assert(pageConfig, { id, pageId })
30
30
  /*/
31
31
  if (!pageConfig)
@@ -3,6 +3,7 @@ export { getConfigValueSourceRelevantAnyEnv };
3
3
  export { isRuntimeEnvMatch };
4
4
  export { isConfigSourceValueNull };
5
5
  import { assert, assertIsNotBrowser } from '../../utils.js';
6
+ import { getFileSuffixes } from '../../../../shared-server-node/getFileSuffixes.js';
6
7
  assertIsNotBrowser();
7
8
  function getConfigValueSourcesRelevant(configName, runtimeEnv, pageConfig) {
8
9
  const configDef = pageConfig.configDefinitions[configName];
@@ -86,10 +87,10 @@ function isConfigSourceValueNull(source) {
86
87
  function applyFilenameSuffix(sourcesRelevant) {
87
88
  const getFileName = (source) => source.plusFile?.filePath.fileName ?? '';
88
89
  // Apply `clear`: truncate at first clear file
89
- const clearIndex = sourcesRelevant.findIndex((source) => getFileName(source).includes('.clear.'));
90
+ const clearIndex = sourcesRelevant.findIndex((source) => getFileSuffixes(getFileName(source)).includes('clear'));
90
91
  if (clearIndex !== -1)
91
92
  sourcesRelevant = sourcesRelevant.slice(0, clearIndex + 1);
92
93
  // Apply `default`: exclude defaults if any non-defaults exist, otherwise keep only first default
93
- const nonDefaults = sourcesRelevant.filter((source) => !getFileName(source).includes('.default.'));
94
+ const nonDefaults = sourcesRelevant.filter((source) => !getFileSuffixes(getFileName(source)).includes('default'));
94
95
  return nonDefaults.length > 0 ? nonDefaults : sourcesRelevant.slice(0, 1);
95
96
  }
@@ -8,10 +8,10 @@ import { reloadVikeConfig, isV1Design, getVikeConfigInternalOptional } from '../
8
8
  import pc from '@brillout/picocolors';
9
9
  import { logConfigInfo } from '../shared/loggerDev.js';
10
10
  import { getFilePathToShowToUserModule } from '../shared/getFilePath.js';
11
- import { isRunnable, updateUserFiles } from '../../../server/runtime/globalContext.js';
11
+ import { updateUserFiles } from '../../../server/runtime/globalContext.js';
12
12
  import { isPlusFile } from '../shared/resolveVikeConfigInternal/crawlPlusFiles.js';
13
13
  import { isTemporaryBuildFile } from '../shared/resolveVikeConfigInternal/transpileAndExecuteFile.js';
14
- import { getVikeConfigError } from '../../../shared-server-node/getVikeConfigError.js';
14
+ import { debugFileChange, getVikeConfigError } from '../../../shared-server-node/getVikeConfigError.js';
15
15
  const filterRolldown = {
16
16
  id: {
17
17
  include: new RegExp(`^(${escapeRegex(virtualFileIdPrefix1)}|${escapeRegex(virtualFileIdPrefix2)})`),
@@ -40,6 +40,7 @@ function pluginVirtualFiles() {
40
40
  },
41
41
  handleHotUpdate: {
42
42
  async handler(ctx) {
43
+ debugFileChange('handleHotUpdate()', ctx.file);
43
44
  try {
44
45
  return await handleHotUpdate(ctx, config);
45
46
  }
@@ -86,9 +87,11 @@ function handleFileAddRemove(server, config) {
86
87
  file = normalizePath(file);
87
88
  if (isTemporaryBuildFile(file))
88
89
  return;
90
+ const operation = isRemove ? 'removed' : 'created';
91
+ debugFileChange('server.watcher', file, operation);
89
92
  const { moduleGraph } = server;
90
93
  const isVikeConfigDep = await isVikeConfigDependency(file, moduleGraph);
91
- const reload = () => reloadConfig(file, config, isRemove ? 'removed' : 'created', server);
94
+ const reload = () => reloadConfig(file, config, operation, server);
92
95
  // Config code
93
96
  if (isVikeConfigDep && !isVikeConfigDep.isProcessedByVite) {
94
97
  reload();
@@ -127,6 +130,7 @@ function invalidateVikeVirtualFiles(server) {
127
130
  async function handleHotUpdate(ctx, config) {
128
131
  const { file, server } = ctx;
129
132
  const isVikeConfigDep = await isVikeConfigDependency(ctx.file, ctx.server.moduleGraph);
133
+ debugFileChange(isVikeConfigDep);
130
134
  if (isVikeConfigDep) {
131
135
  if (!isVikeConfigDep.isProcessedByVite) {
132
136
  /* Tailwind breaks this assertion, see https://github.com/vikejs/vike/discussions/1330#discussioncomment-7787238
@@ -141,11 +145,9 @@ async function handleHotUpdate(ctx, config) {
141
145
  }
142
146
  else {
143
147
  // Ensure we invalidate `file` *before* server.ssrLoadModule() in updateUserFiles()
144
- // Vite already invalidates it, but *after* handleHotUpdate() and thus after server.ssrLoadModule()
148
+ // Vite also invalidates it, but *after* handleHotUpdate() and thus after server.ssrLoadModule()
145
149
  ctx.modules.forEach((mod) => server.moduleGraph.invalidateModule(mod));
146
- if (isRunnable(server)) {
147
- await updateUserFiles();
148
- }
150
+ await updateUserFiles();
149
151
  }
150
152
  }
151
153
  }
@@ -172,12 +174,12 @@ async function isVikeConfigDependency(filePathAbsoluteFilesystem, moduleGraph) {
172
174
  return { isProcessedByVite: true };
173
175
  return null;
174
176
  }
175
- function reloadConfig(filePath, config, op, server) {
177
+ function reloadConfig(filePath, config, operation, server) {
176
178
  // Ensure server.ssrLoadModule() loads fresh Vike virtual files (`reloadConfig()` > `updateUserFiles()` > `server.ssrLoadModule()`)
177
179
  invalidateVikeVirtualFiles(server);
178
180
  {
179
181
  const filePathToShowToUserResolved = getFilePathToShowToUserModule(filePath, config);
180
- const msg = `${op} ${pc.dim(filePathToShowToUserResolved)}`;
182
+ const msg = `${operation} ${pc.dim(filePathToShowToUserResolved)}`;
181
183
  logConfigInfo(msg, 'info');
182
184
  }
183
185
  reloadVikeConfig();
@@ -114,6 +114,14 @@ const configDefinitionsBuiltIn = {
114
114
  .flat(1)
115
115
  // Server-only
116
116
  .filter((source) => !source.configEnv.client)
117
+ // Exclude `.ssr.js` hooks (they don't require pageContext.json requests)
118
+ .filter((source) => {
119
+ const { definedAt } = source;
120
+ if ('filePathAbsoluteVite' in definedAt && definedAt.filePathAbsoluteVite.includes('.ssr.')) {
121
+ return false;
122
+ }
123
+ return true;
124
+ })
117
125
  // Config value isn't `null`
118
126
  .filter((source) => !isConfigSourceValueNull(source));
119
127
  return sources.length > 0;
@@ -12,6 +12,7 @@ export { getConfigDefinitionOptional };
12
12
  export { getVikeConfigFromCliOrEnv };
13
13
  import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, includes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, assertKeys, objectKeys, objectFromEntries, unique, isCallable, makeFirst, lowerFirst, makeLast, genPromise, checkType, objectAssign, getGlobalObject, } from '../utils.js';
14
14
  import { configDefinitionsBuiltIn, } from './resolveVikeConfigInternal/configDefinitionsBuiltIn.js';
15
+ import { getFileSuffixes } from '../../../shared-server-node/getFileSuffixes.js';
15
16
  import { getLocationId, getFilesystemRouteString, getFilesystemRouteDefinedBy, isInherited, sortAfterInheritanceOrder, applyFilesystemRoutingRootEffect, } from './resolveVikeConfigInternal/filesystemRouting.js';
16
17
  import { getViteDevServer, vikeConfigErrorRecoverMsg } from '../../../server/runtime/globalContext.js';
17
18
  import { logConfigInfo, logErrorServerDev } from './loggerDev.js';
@@ -1066,16 +1067,16 @@ function getConfVal(plusFile, configName) {
1066
1067
  function resolveConfigEnv(configEnv, filePath) {
1067
1068
  const configEnvResolved = { ...configEnv };
1068
1069
  if (filePath.filePathAbsoluteFilesystem) {
1069
- const { fileName } = filePath;
1070
- if (fileName.includes('.server.')) {
1070
+ const suffixes = getFileSuffixes(filePath.fileName);
1071
+ if (suffixes.includes('ssr') || suffixes.includes('server')) {
1071
1072
  configEnvResolved.server = true;
1072
1073
  configEnvResolved.client = false;
1073
1074
  }
1074
- else if (fileName.includes('.client.')) {
1075
+ else if (suffixes.includes('client')) {
1075
1076
  configEnvResolved.client = true;
1076
1077
  configEnvResolved.server = false;
1077
1078
  }
1078
- else if (fileName.includes('.shared.')) {
1079
+ else if (suffixes.includes('shared')) {
1079
1080
  configEnvResolved.server = true;
1080
1081
  configEnvResolved.client = true;
1081
1082
  }
@@ -0,0 +1 @@
1
+ export { startupLog } from '../../node/api/dev.js';
@@ -0,0 +1 @@
1
+ export { startupLog } from '../../node/api/dev.js';