vike 0.4.199 → 0.4.200-commit-de0e6ef

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/cjs/node/client/router.js +3 -1
  2. package/dist/cjs/node/plugin/plugins/envVars.js +3 -0
  3. package/dist/cjs/node/plugin/plugins/extractAssetsPlugin.js +2 -0
  4. package/dist/cjs/node/plugin/plugins/extractExportNamesPlugin.js +2 -0
  5. package/dist/cjs/node/plugin/plugins/fileEnv.js +2 -0
  6. package/dist/cjs/node/plugin/plugins/importBuild/index.js +4 -4
  7. package/dist/cjs/node/plugin/plugins/importUserCode/index.js +7 -6
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +15 -3
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +1 -1
  10. package/dist/cjs/node/plugin/shared/normalizeId.js +9 -0
  11. package/dist/cjs/node/prerender/runPrerender.js +3 -1
  12. package/dist/cjs/node/runtime/globalContext/loadImportBuild.js +1 -1
  13. package/dist/cjs/node/runtime/renderPage.js +15 -5
  14. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  15. package/dist/cjs/utils/parseUrl-extras.js +4 -3
  16. package/dist/esm/client/client-routing-runtime/history.d.ts +19 -9
  17. package/dist/esm/client/client-routing-runtime/history.js +121 -68
  18. package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
  19. package/dist/esm/client/client-routing-runtime/index.js +1 -0
  20. package/dist/esm/client/client-routing-runtime/initClientRouter.js +2 -5
  21. package/dist/esm/client/client-routing-runtime/initOnPopState.d.ts +12 -0
  22. package/dist/esm/client/client-routing-runtime/initOnPopState.js +72 -0
  23. package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +1 -2
  24. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +4 -6
  25. package/dist/esm/node/client/router.d.ts +2 -0
  26. package/dist/esm/node/client/router.js +2 -0
  27. package/dist/esm/node/plugin/plugins/envVars.js +3 -0
  28. package/dist/esm/node/plugin/plugins/extractAssetsPlugin.js +2 -0
  29. package/dist/esm/node/plugin/plugins/extractExportNamesPlugin.js +2 -0
  30. package/dist/esm/node/plugin/plugins/fileEnv.js +2 -0
  31. package/dist/esm/node/plugin/plugins/importBuild/index.js +5 -5
  32. package/dist/esm/node/plugin/plugins/importUserCode/index.js +8 -7
  33. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +16 -4
  34. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +1 -1
  35. package/dist/esm/node/plugin/shared/normalizeId.d.ts +2 -0
  36. package/dist/esm/node/plugin/shared/normalizeId.js +7 -0
  37. package/dist/esm/node/prerender/runPrerender.js +3 -1
  38. package/dist/esm/node/runtime/globalContext/loadImportBuild.js +2 -2
  39. package/dist/esm/node/runtime/renderPage.js +16 -6
  40. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  41. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  42. package/dist/esm/utils/getCurrentUrl.d.ts +1 -1
  43. package/dist/esm/utils/parseUrl-extras.d.ts +2 -2
  44. package/dist/esm/utils/parseUrl-extras.js +4 -3
  45. package/dist/esm/utils/projectInfo.d.ts +1 -1
  46. package/package.json +2 -11
  47. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +0 -4
  48. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +0 -63
@@ -0,0 +1,72 @@
1
+ export { initOnPopState };
2
+ export { onPopState };
3
+ import { assertWarning, getGlobalObject } from './utils.js';
4
+ import { onPopStateBegin } from './history.js';
5
+ import { renderPageClientSide } from './renderPageClientSide.js';
6
+ import { setScrollPosition } from './setScrollPosition.js';
7
+ const globalObject = getGlobalObject('initOnPopState.ts', { listeners: [] });
8
+ function initOnPopState() {
9
+ // - The popstate event is trigged upon:
10
+ // - Back-/forward navigation.
11
+ // - By user clicking on his browser's back-/forward navigation (or using a shortcut)
12
+ // - By JavaScript: `history.back()` / `history.forward()`
13
+ // - URL hash change.
14
+ // - Click on `<a href="#some-hash" />`
15
+ // - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
16
+ // - `location.hash = 'some-hash'`
17
+ // - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
18
+ window.addEventListener('popstate', async () => {
19
+ const { isNewState, previous, current } = onPopStateBegin();
20
+ const scrollTarget = current.state.scrollPosition || undefined;
21
+ const isUserPushStateNavigation = current.state.triggeredBy === 'user' || previous.state.triggeredBy === 'user';
22
+ const isHashNavigation = removeHash(current.url) === removeHash(previous.url) && current.url !== previous.url;
23
+ // - `isNewState === true` when:
24
+ // - Click on `<a href="#some-hash" />` (note that Vike's `initOnLinkClick()` handler skips hash links)
25
+ // - `location.hash = 'some-hash'`
26
+ // - `isNewState === false` when `popstate` was triggered by the user clicking on his browser's forward/backward history button.
27
+ const isHashNavigationNew = isHashNavigation && isNewState;
28
+ const isBackwardNavigation = !current.state.timestamp || !previous.state.timestamp ? null : current.state.timestamp < previous.state.timestamp;
29
+ // We have to scroll ourselves because we use `window.history.scrollRestoration = 'manual'`. So far this seems to work. Alternatives in case it doesn't work:
30
+ // - Alternative: we use `window.history.scrollRestoration = 'auto'`
31
+ // - Problem: I don't think it's possbible to set `window.history.scrollRestoration = 'auto'` only for hash navigation and not for non-hash navigations?
32
+ // - Problem: inconsistencies between browsers? For example specification says that setting `window.history.scrollRestoration` only affects the current entry in the session history but this contradicts what people are experiencing in practice.
33
+ // - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
34
+ // - Practice: https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
35
+ // - Alternative: we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
36
+ // - By using the `hashchange` event.
37
+ // - Problem: conflict if user wants to override the browser's default behavior? E.g. for smooth scrolling, or when using hashes for saving states of some fancy animations.
38
+ if (isHashNavigation) {
39
+ if (!isHashNavigationNew) {
40
+ setScrollPosition(scrollTarget);
41
+ }
42
+ else {
43
+ // The browser already scrolled to `#${hash}` => the current scroll position is the right one => we saved it with `enhanceHistoryState()`.
44
+ }
45
+ return;
46
+ }
47
+ let doNotRenderIfSamePage = isUserPushStateNavigation;
48
+ let abort;
49
+ globalObject.listeners.forEach((listener) => {
50
+ abort || (abort = listener({ previous }));
51
+ });
52
+ if (abort) {
53
+ return;
54
+ }
55
+ if (abort === false) {
56
+ doNotRenderIfSamePage = false;
57
+ }
58
+ await renderPageClientSide({ scrollTarget, isBackwardNavigation, doNotRenderIfSamePage });
59
+ });
60
+ }
61
+ // TODO/eventually: deprecate this onPopState(listener) function and let the user define +onPopState.js instead?
62
+ /** Control back-/forward navigation.
63
+ *
64
+ * https://vike.dev/onPopState
65
+ */
66
+ function onPopState(listener) {
67
+ assertWarning(false, 'onPopState() is experimental', { onlyOnce: true });
68
+ globalObject.listeners.push(listener);
69
+ }
70
+ function removeHash(url) {
71
+ return url.split('#')[0];
72
+ }
@@ -12,8 +12,7 @@ type RenderArgs = {
12
12
  overwriteLastHistoryEntry?: boolean;
13
13
  pageContextsFromRewrite?: PageContextFromRewrite[];
14
14
  redirectCount?: number;
15
- /** Whether the navigation was triggered by the user land calling `history.pushState()` */
16
- isUserLandPushStateNavigation?: boolean;
15
+ doNotRenderIfSamePage?: boolean;
17
16
  isClientSideNavigation?: boolean;
18
17
  };
19
18
  declare function renderPageClientSide(renderArgs: RenderArgs): Promise<void>;
@@ -10,12 +10,11 @@ import { assertInfo, assertWarning, isReact } from './utils.js';
10
10
  import { executeOnRenderClientHook } from '../shared/executeOnRenderClientHook.js';
11
11
  import { assertHook, getHook } from '../../shared/hooks/getHook.js';
12
12
  import { isErrorFetchingStaticAssets, loadUserFilesClientSide } from '../shared/loadUserFilesClientSide.js';
13
- import { pushHistory } from './history.js';
13
+ import { pushHistoryState } from './history.js';
14
14
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
15
15
  import { route } from '../../shared/route/index.js';
16
16
  import { isClientSideRoutable } from './isClientSideRoutable.js';
17
17
  import { setScrollPosition } from './setScrollPosition.js';
18
- import { updateState } from './onBrowserHistoryNavigation.js';
19
18
  import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
20
19
  import { getErrorPageId } from '../../shared/error-page.js';
21
20
  import { setPageContextCurrent } from './getPageContextCurrent.js';
@@ -30,7 +29,7 @@ const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
30
29
  })());
31
30
  const { firstRenderStartPromise } = globalObject;
32
31
  async function renderPageClientSide(renderArgs) {
33
- const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
32
+ const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, doNotRenderIfSamePage, isClientSideNavigation = true } = renderArgs;
34
33
  let { scrollTarget } = renderArgs;
35
34
  const { previousPageContext } = globalObject;
36
35
  addLinkPrefetchHandlers_unwatch();
@@ -120,7 +119,7 @@ async function renderPageClientSide(renderArgs) {
120
119
  const isSamePage = pageContextFromRoute.pageId &&
121
120
  previousPageContext?.pageId &&
122
121
  pageContextFromRoute.pageId === previousPageContext.pageId;
123
- if (isUserLandPushStateNavigation && isSamePage) {
122
+ if (doNotRenderIfSamePage && isSamePage) {
124
123
  // Skip's Vike's rendering; let the user handle the navigation
125
124
  return;
126
125
  }
@@ -476,8 +475,7 @@ function changeUrl(url, overwriteLastHistoryEntry) {
476
475
  if (getCurrentUrl() === url)
477
476
  return;
478
477
  browserNativeScrollRestoration_disable();
479
- pushHistory(url, overwriteLastHistoryEntry);
480
- updateState();
478
+ pushHistoryState(url, overwriteLastHistoryEntry);
481
479
  }
482
480
  function handleErrorFetchingStaticAssets(err, pageContext, isFirstRender) {
483
481
  if (!isErrorFetchingStaticAssets(err)) {
@@ -1,6 +1,8 @@
1
1
  export { navigate };
2
2
  export { reload };
3
3
  export { prefetch };
4
+ export { onPopState };
4
5
  declare const navigate: never;
5
6
  declare const reload: never;
6
7
  declare const prefetch: never;
8
+ declare const onPopState: never;
@@ -1,11 +1,13 @@
1
1
  export { navigate };
2
2
  export { reload };
3
3
  export { prefetch };
4
+ export { onPopState };
4
5
  import { assertWarning } from '../../utils/assert.js';
5
6
  // `never` to ensure package.json#exports["./client/router"].types points to type defined by the client-side code
6
7
  const navigate = (() => warnNoEffect('navigate'));
7
8
  const reload = (() => warnNoEffect('reload'));
8
9
  const prefetch = (() => warnNoEffect('prefetch'));
10
+ const onPopState = (() => { });
9
11
  function warnNoEffect(caller) {
10
12
  assertWarning(false, `Calling ${caller}() on the server-side has no effect`, {
11
13
  showStackTrace: true,
@@ -3,6 +3,7 @@ import { loadEnv } from 'vite';
3
3
  import { assert, assertPosixPath, assertUsage, assertWarning, escapeRegex, isArray, lowerFirst } from '../utils.js';
4
4
  import { sourceMapPassthrough } from '../shared/rollupSourceMap.js';
5
5
  import { getModuleFilePathAbsolute } from '../shared/getFilePath.js';
6
+ import { normalizeId } from '../shared/normalizeId.js';
6
7
  // TODO/enventually: (after we implemented vike.config.js)
7
8
  // - Make import.meta.env work inside +config.js
8
9
  // - For it to work, we'll probably need the user to define the settings (e.g. `envDir`) for loadEnv() inside vike.config.js instead of vite.config.js
@@ -25,9 +26,11 @@ function envVarsPlugin() {
25
26
  config.plugins.sort(lowerFirst((plugin) => (plugin.name === 'vite:define' ? 1 : 0)));
26
27
  },
27
28
  transform(code, id, options) {
29
+ id = normalizeId(id);
28
30
  assertPosixPath(id);
29
31
  if (id.includes('/node_modules/'))
30
32
  return;
33
+ assertPosixPath(config.root);
31
34
  if (!id.startsWith(config.root))
32
35
  return;
33
36
  if (!code.includes('import.meta.env.'))
@@ -16,6 +16,7 @@ import pc from '@brillout/picocolors';
16
16
  import { fixServerAssets_isEnabled } from './buildConfig/fixServerAssets.js';
17
17
  import { getVikeConfig, isV1Design } from './importUserCode/v1-design/getVikeConfig.js';
18
18
  import { assertV1Design } from '../../shared/assertV1Design.js';
19
+ import { normalizeId } from '../shared/normalizeId.js';
19
20
  const extractAssetsRE = /(\?|&)extractAssets(?:&|$)/;
20
21
  const rawRE = /(\?|&)raw(?:&|$)/;
21
22
  const urlRE = /(\?|&)url(?:&|$)/;
@@ -34,6 +35,7 @@ function extractAssetsPlugin() {
34
35
  apply: 'build',
35
36
  enforce: 'post',
36
37
  async transform(src, id, options) {
38
+ id = normalizeId(id);
37
39
  if (!extractAssetsRE.test(id)) {
38
40
  return;
39
41
  }
@@ -4,6 +4,7 @@ export { extractExportNamesRE };
4
4
  import { assert, getFileExtension, viteIsSSR_options, createDebugger, getGlobalObject, assertUsage } from '../utils.js';
5
5
  import { getExportNames } from '../shared/parseEsModule.js';
6
6
  import { sourceMapRemove } from '../shared/rollupSourceMap.js';
7
+ import { normalizeId } from '../shared/normalizeId.js';
7
8
  const extractExportNamesRE = /(\?|&)extractExportNames(?:&|$)/;
8
9
  const debug = createDebugger('vike:extractExportNames');
9
10
  const globalObject = getGlobalObject('extractExportNamesPlugin.ts', {});
@@ -13,6 +14,7 @@ function extractExportNamesPlugin() {
13
14
  name: 'vike:extractExportNames',
14
15
  enforce: 'post',
15
16
  async transform(src, id, options) {
17
+ id = normalizeId(id);
16
18
  const isClientSide = !viteIsSSR_options(options);
17
19
  if (extractExportNamesRE.test(id)) {
18
20
  const code = await getExtractExportNamesCode(src, isClientSide, !isDev, id);
@@ -6,6 +6,7 @@ import pc from '@brillout/picocolors';
6
6
  import { getModuleFilePathAbsolute } from '../shared/getFilePath.js';
7
7
  import { sourceMapRemove } from '../shared/rollupSourceMap.js';
8
8
  import { getExportNames } from '../shared/parseEsModule.js';
9
+ import { normalizeId } from '../shared/normalizeId.js';
9
10
  function fileEnv() {
10
11
  let config;
11
12
  let viteDevServer;
@@ -31,6 +32,7 @@ function fileEnv() {
31
32
  },
32
33
  // In production, we have to use transform() to replace modules with a runtime error because generateBundle() doesn't work for dynamic imports. In production, dynamic imports can only be verified at runtime.
33
34
  async transform(code, id, options) {
35
+ id = normalizeId(id);
34
36
  // In dev, only using load() is enough as it also works for dynamic imports (see sibling comment).
35
37
  if (viteDevServer)
36
38
  return;
@@ -1,6 +1,6 @@
1
1
  export { importBuild };
2
2
  export { set_ASSETS_MAP };
3
- import { serverEntryPlugin } from '@brillout/vite-plugin-server-entry/plugin';
3
+ import { serverProductionEntryPlugin } from '@brillout/vite-plugin-server-entry/plugin';
4
4
  import { assert, getOutDirs, toPosixPath } from '../../utils.js';
5
5
  import path from 'path';
6
6
  import { createRequire } from 'module';
@@ -24,15 +24,15 @@ function importBuild() {
24
24
  configVike = await getConfigVike(config);
25
25
  }
26
26
  },
27
- ...serverEntryPlugin({
28
- getImporterCode: () => {
29
- return getEntryCode(config, configVike);
27
+ ...serverProductionEntryPlugin({
28
+ getServerProductionEntry: () => {
29
+ return getServerProductionEntryCode(config, configVike);
30
30
  },
31
31
  libraryName: 'Vike'
32
32
  })
33
33
  ];
34
34
  }
35
- function getEntryCode(config, configVike) {
35
+ function getServerProductionEntryCode(config, configVike) {
36
36
  const importPath = getImportPath(config);
37
37
  const vikeManifest = getVikeManifest(configVike);
38
38
  const importerCode = [
@@ -6,7 +6,7 @@ import { getVirtualFileImportUserCode } from './getVirtualFileImportUserCode.js'
6
6
  import { assert, assertPosixPath, getOutDirs, getVirtualFileId, isDev3, isVirtualFileId, resolveVirtualFileId } from '../../utils.js';
7
7
  import { isVirtualFileIdPageConfigValuesAll } from '../../../shared/virtual-files/virtualFilePageConfigValuesAll.js';
8
8
  import { isVirtualFileIdImportUserCode } from '../../../shared/virtual-files/virtualFileImportUserCode.js';
9
- import { vikeConfigDependencies, reloadVikeConfig, isVikeConfigFile } from './v1-design/getVikeConfig.js';
9
+ import { vikeConfigDependencies, reloadVikeConfig, isVikeConfigFile, isV1Design } from './v1-design/getVikeConfig.js';
10
10
  import pc from '@brillout/picocolors';
11
11
  import { logConfigInfo } from '../../shared/loggerNotProd.js';
12
12
  import { getModuleFilePathAbsolute } from '../../shared/getFilePath.js';
@@ -18,16 +18,17 @@ function importUserCode() {
18
18
  name: 'vike:importUserCode',
19
19
  config(_, env) {
20
20
  isDev = isDev3(env);
21
- return {
22
- experimental: {
23
- // TODO/v1-release: remove
24
- importGlobRestoreExtension: true
25
- }
26
- };
27
21
  },
28
22
  async configResolved(config_) {
29
23
  configVike = await getConfigVike(config_);
30
24
  config = config_;
25
+ // TODO/v1-release: remove
26
+ {
27
+ assert(isDev !== undefined);
28
+ const isV1 = await isV1Design(config, isDev);
29
+ if (!isV1)
30
+ config.experimental.importGlobRestoreExtension = true;
31
+ }
31
32
  },
32
33
  resolveId(id) {
33
34
  if (isVirtualFileId(id)) {
@@ -2,7 +2,7 @@ export { transpileAndExecuteFile };
2
2
  export { getConfigBuildErrorFormatted };
3
3
  export { getConfigExecutionErrorIntroMsg };
4
4
  export { isTemporaryBuildFile };
5
- import { build, formatMessages } from 'esbuild';
5
+ import { build, formatMessages, version } from 'esbuild';
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
8
  import pc from '@brillout/picocolors';
@@ -14,6 +14,8 @@ import 'source-map-support/register.js';
14
14
  import { getFilePathAbsoluteUserRootDir } from '../../../../shared/getFilePath.js';
15
15
  assertIsNotProductionRuntime();
16
16
  const debug = createDebugger('vike:pointer-imports');
17
+ console.log('esbuild version', version);
18
+ console.log('require.resolve("vike-react/config")', require.resolve('vike-react/config'));
17
19
  async function transpileAndExecuteFile(filePath, userRootDir, isConfigFile) {
18
20
  const { filePathAbsoluteFilesystem, filePathToShowToUserResolved } = filePath;
19
21
  const fileExtension = getFileExtension(filePathAbsoluteFilesystem);
@@ -83,7 +85,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
83
85
  metafile: true,
84
86
  bundle: true
85
87
  };
86
- let pointerImports = {};
88
+ const pointerImports = {};
87
89
  options.plugins = [
88
90
  // Determine whether an import should be:
89
91
  // - A pointer import
@@ -93,6 +95,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
93
95
  setup(build) {
94
96
  // https://github.com/brillout/esbuild-playground
95
97
  build.onResolve({ filter: /.*/ }, async (args) => {
98
+ console.log('onResolve()', JSON.stringify(args, null, 2));
96
99
  if (args.kind !== 'import-statement')
97
100
  return;
98
101
  // Avoid infinite loop: https://github.com/evanw/esbuild/issues/3095#issuecomment-1546916366
@@ -101,14 +104,23 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
101
104
  return;
102
105
  const { path, ...opts } = args;
103
106
  opts.pluginData = { [useEsbuildResolver]: true };
104
- const resolved = await build.resolve(path, opts);
107
+ let resolved = await build.resolve(path, opts);
105
108
  if (resolved.errors.length > 0) {
109
+ let resolvedWithNode;
110
+ try {
111
+ resolvedWithNode = require.resolve(args.path, { paths: [args.resolveDir] });
112
+ }
113
+ catch { }
114
+ if (resolvedWithNode)
115
+ resolved = { path: resolvedWithNode };
116
+ }
117
+ if (resolved.errors && resolved.errors.length > 0) {
106
118
  /* We could do the following to let Node.js throw the error, but we don't because the error shown by esbuild is prettier: the Node.js error refers to the transpiled [build-f7i251e0iwnw]+config.ts.mjs whereas esbuild refers to the source +config.ts file.
107
119
  pointerImports[args.path] = false
108
120
  return { external: true }
109
121
  */
110
- cleanEsbuildErrors(resolved.errors);
111
122
  // Let esbuild throw the error
123
+ cleanEsbuildErrors(resolved.errors);
112
124
  return resolved;
113
125
  }
114
126
  assert(resolved.path);
@@ -21,7 +21,7 @@ async function getVirtualFilePageConfigValuesAll(id, isDev, config) {
21
21
  const { pageId, isForClientSide } = result;
22
22
  const { pageConfigs } = await getVikeConfig(config, isDev, { tolerateInvalidConfig: true });
23
23
  const pageConfig = pageConfigs.find((pageConfig) => pageConfig.pageId === pageId);
24
- assert(pageConfig);
24
+ assert(pageConfig, { id, pageId });
25
25
  const configVike = await getConfigVike(config);
26
26
  const code = getLoadConfigValuesAll(pageConfig, isForClientSide, pageId, configVike.includeAssetsImportedByServer, isDev);
27
27
  debug(id, isForClientSide ? 'CLIENT-SIDE' : 'SERVER-SIDE', code);
@@ -0,0 +1,2 @@
1
+ export { normalizeId };
2
+ declare function normalizeId(id: string): string;
@@ -0,0 +1,7 @@
1
+ export { normalizeId };
2
+ import { toPosixPath } from '../utils.js';
3
+ // In principle Vite/Rollup should always normalize the `id` in `transform(code, id)` but it seems to not always do it.
4
+ // https://github.com/vikejs/vike/issues/1935
5
+ function normalizeId(id) {
6
+ return toPosixPath(id);
7
+ }
@@ -577,7 +577,9 @@ async function write(urlOriginal, pageContext, fileExtension, fileContent, root,
577
577
  assertPosixPath(fileUrl);
578
578
  assert(fileUrl.startsWith('/'));
579
579
  const filePathRelative = fileUrl.slice(1);
580
- assert(!filePathRelative.startsWith('/'));
580
+ assert(!filePathRelative.startsWith('/'),
581
+ // Let's remove this debug info after we add a assertUsage() avoiding https://github.com/vikejs/vike/issues/1929
582
+ { urlOriginal, fileUrl });
581
583
  assertPosixPath(outDirClient);
582
584
  assertPosixPath(filePathRelative);
583
585
  const filePath = path.posix.join(outDirClient, filePathRelative);
@@ -1,6 +1,6 @@
1
1
  export { loadImportBuild };
2
2
  export { setImportBuildGetters };
3
- import { importServerEntry } from '@brillout/vite-plugin-server-entry/runtime';
3
+ import { importServerProductionEntry } from '@brillout/vite-plugin-server-entry/runtime';
4
4
  import { assert } from '../utils.js';
5
5
  const buildGetters = (globalThis.__vike_buildGetters = globalThis.__vike_buildGetters || {
6
6
  getters: null
@@ -10,7 +10,7 @@ function setImportBuildGetters(getters) {
10
10
  }
11
11
  async function loadImportBuild(outDir) {
12
12
  if (!buildGetters.getters) {
13
- await importServerEntry(outDir);
13
+ await importServerProductionEntry({ outDir });
14
14
  assert(buildGetters.getters);
15
15
  }
16
16
  const [pageFiles, assetsManifest, pluginManifest] = await Promise.all([
@@ -2,7 +2,7 @@ export { renderPage };
2
2
  export { renderPage_addWrapper };
3
3
  import { getRenderContext, getPageContextInitEnhanced, renderPageAlreadyRouted } from './renderPage/renderPageAlreadyRouted.js';
4
4
  import { route } from '../../shared/route/index.js';
5
- import { assert, hasProp, objectAssign, isUrl, parseUrl, assertEnv, assertWarning, getGlobalObject, checkType, assertUsage, normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, addUrlOrigin, createUrlFromComponents, isUri, getUrlPretty } from './utils.js';
5
+ import { assert, hasProp, objectAssign, isUrl, parseUrl, assertEnv, assertWarning, getGlobalObject, checkType, assertUsage, normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, setUrlOrigin, createUrlFromComponents, isUri, getUrlPretty } from './utils.js';
6
6
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
7
7
  import { getGlobalContext, initGlobalContext_renderPage } from './globalContext.js';
8
8
  import { handlePageContextRequestUrl } from './renderPage/handlePageContextRequestUrl.js';
@@ -374,19 +374,29 @@ function getPermanentRedirect(pageContextInit, httpRequestId) {
374
374
  urlTarget = urlTargetExternal;
375
375
  }
376
376
  else {
377
- if (origin)
378
- urlTarget = addUrlOrigin(urlTarget, origin);
379
- if (urlTarget === urlWithoutBase)
377
+ let originChanged = false;
378
+ if (origin) {
379
+ const urlModified = setUrlOrigin(urlTarget, origin);
380
+ if (urlModified !== false) {
381
+ originChanged = true;
382
+ urlTarget = urlModified;
383
+ }
384
+ }
385
+ if (normalize(urlTarget) === normalize(urlWithoutBase))
380
386
  return null;
381
- urlTarget = prependBase(urlTarget, baseServer);
387
+ if (!originChanged)
388
+ urlTarget = prependBase(urlTarget, baseServer);
382
389
  assert(urlTarget !== pageContextInit.urlOriginal);
383
390
  }
384
- logRuntimeInfo?.(`Permanent redirect defined by your config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
391
+ logRuntimeInfo?.(`Permanent redirection defined by config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
385
392
  const httpResponse = createHttpResponseRedirect({ url: urlTarget, statusCode: 301 }, urlWithoutBase);
386
393
  const pageContextHttpResponse = createPageContext(pageContextInit);
387
394
  objectAssign(pageContextHttpResponse, { httpResponse });
388
395
  return pageContextHttpResponse;
389
396
  }
397
+ function normalize(url) {
398
+ return url || '/';
399
+ }
390
400
  async function handleAbortError(errAbort, pageContextsFromRewrite, pageContextInit,
391
401
  // handleAbortError() creates a new pageContext object and we don't merge pageContextNominalPageInit to it: we only use some pageContextNominalPageInit information.
392
402
  pageContextNominalPageInit, httpRequestId, renderContext, pageContextErrorPageInit) {
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.199";
1
+ export declare const PROJECT_VERSION: "0.4.200-commit-de0e6ef";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.199';
2
+ export const PROJECT_VERSION = '0.4.200-commit-de0e6ef';
@@ -1,4 +1,4 @@
1
1
  export { getCurrentUrl };
2
2
  declare function getCurrentUrl(options?: {
3
3
  withoutHash: true;
4
- }): string;
4
+ }): `/${string}`;
@@ -4,7 +4,7 @@ export { normalizeUrlPathname };
4
4
  export { removeBaseServer };
5
5
  export { modifyUrlPathname };
6
6
  export { removeUrlOrigin };
7
- export { addUrlOrigin };
7
+ export { setUrlOrigin };
8
8
  export { getUrlPretty };
9
9
  declare function prependBase(url: string, baseServer: string): string;
10
10
  declare function removeBaseServer(url: string, baseServer: string): string;
@@ -15,5 +15,5 @@ declare function removeUrlOrigin(url: string): {
15
15
  urlModified: string;
16
16
  origin: string | null;
17
17
  };
18
- declare function addUrlOrigin(url: string, origin: string | null): string;
18
+ declare function setUrlOrigin(url: string, origin: string | null): false | string;
19
19
  declare function getUrlPretty(url: string): string;
@@ -4,7 +4,7 @@ export { normalizeUrlPathname };
4
4
  export { removeBaseServer };
5
5
  export { modifyUrlPathname };
6
6
  export { removeUrlOrigin };
7
- export { addUrlOrigin };
7
+ export { setUrlOrigin };
8
8
  export { getUrlPretty };
9
9
  import { assertUrlComponents, createUrlFromComponents, isBaseServer, parseUrl } from './parseUrl.js';
10
10
  import { assert } from './assert.js';
@@ -94,9 +94,10 @@ function removeUrlOrigin(url) {
94
94
  const urlModified = createUrlFromComponents(null, pathnameOriginal, searchOriginal, hashOriginal);
95
95
  return { urlModified, origin };
96
96
  }
97
- function addUrlOrigin(url, origin) {
97
+ function setUrlOrigin(url, origin) {
98
98
  const { origin: originCurrent, pathnameOriginal, searchOriginal, hashOriginal } = parseUrl(url, '/');
99
- assert(originCurrent === null);
99
+ if (origin === originCurrent)
100
+ return false;
100
101
  assert(origin === null || origin.startsWith('http'));
101
102
  const urlModified = createUrlFromComponents(origin, pathnameOriginal, searchOriginal, hashOriginal);
102
103
  return urlModified;
@@ -1,4 +1,4 @@
1
1
  export declare const projectInfo: {
2
2
  projectName: "Vike";
3
- projectVersion: "0.4.199";
3
+ projectVersion: "0.4.200-commit-de0e6ef";
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.199",
3
+ "version": "0.4.200-commit-de0e6ef",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -125,14 +125,13 @@
125
125
  "@brillout/json-serializer": "^0.5.13",
126
126
  "@brillout/picocolors": "^1.0.15",
127
127
  "@brillout/require-shim": "^0.1.2",
128
- "@brillout/vite-plugin-server-entry": "^0.4.11",
128
+ "@brillout/vite-plugin-server-entry": "^0.5.0",
129
129
  "acorn": "^8.0.0",
130
130
  "cac": "^6.0.0",
131
131
  "es-module-lexer": "^1.0.0",
132
132
  "esbuild": "^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0",
133
133
  "fast-glob": "^3.0.0",
134
134
  "semver": "^7.0.0",
135
- "sirv": "^2.0.0",
136
135
  "source-map-support": "^0.5.0"
137
136
  },
138
137
  "peerDependencies": {
@@ -232,16 +231,8 @@
232
231
  "@types/resolve": "^1.20.6",
233
232
  "@types/semver": "^7.5.8",
234
233
  "@types/source-map-support": "^0.5.10",
235
- "acorn": "^8.11.2",
236
- "cac": "^6.7.14",
237
- "es-module-lexer": "^1.4.1",
238
- "esbuild": "^0.23.0",
239
- "fast-glob": "^3.3.2",
240
234
  "react-streaming": "^0.3.43",
241
235
  "rimraf": "^5.0.5",
242
- "semver": "^7.6.3",
243
- "sirv": "^2.0.4",
244
- "source-map-support": "^0.5.21",
245
236
  "typescript": "^5.6.2",
246
237
  "vite": "^5.4.0"
247
238
  },
@@ -1,4 +0,0 @@
1
- export { onBrowserHistoryNavigation };
2
- export { updateState };
3
- declare function onBrowserHistoryNavigation(): void;
4
- declare function updateState(): void;
@@ -1,63 +0,0 @@
1
- export { onBrowserHistoryNavigation };
2
- export { updateState };
3
- import { getCurrentUrl, getGlobalObject } from './utils.js';
4
- import { initHistoryState, getHistoryState } from './history.js';
5
- import { renderPageClientSide } from './renderPageClientSide.js';
6
- import { setScrollPosition } from './setScrollPosition.js';
7
- const globalObject = getGlobalObject('onBrowserHistoryNavigation.ts', { previousState: getState() });
8
- function onBrowserHistoryNavigation() {
9
- // - The popstate event is trigged upon:
10
- // - Back-/forward navigation.
11
- // - By user clicking on his browser's back-/forward navigation (or using a shortcut)
12
- // - By JavaScript: `history.back()` / `history.forward()`
13
- // - URL hash change.
14
- // - By user clicking on a hash link `<a href="#some-hash" />`
15
- // - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
16
- // - By JavaScript: `location.hash = 'some-hash'`
17
- // - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
18
- window.addEventListener('popstate', async () => {
19
- const currentState = getState();
20
- const scrollTarget = currentState.historyState.scrollPosition || undefined;
21
- const isUserLandPushStateNavigation = currentState.historyState.triggeredBy === 'user';
22
- const isHashNavigation = currentState.urlWithoutHash === globalObject.previousState.urlWithoutHash;
23
- const isBackwardNavigation = !currentState.historyState.timestamp || !globalObject.previousState.historyState.timestamp
24
- ? null
25
- : currentState.historyState.timestamp < globalObject.previousState.historyState.timestamp;
26
- globalObject.previousState = currentState;
27
- if (isHashNavigation && !isUserLandPushStateNavigation) {
28
- // - `history.state` is uninitialized (`null`) when:
29
- // - The user's code runs `window.location.hash = '#section'`.
30
- // - The user clicks on an anchor link `<a href="#section">Section</a>` (because Vike's `initOnLinkClick()` handler skips hash links).
31
- // - `history.state` is `null` when uninitialized: https://developer.mozilla.org/en-US/docs/Web/API/History/state
32
- // - Alternatively, we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
33
- // - Problem: we cannot intercept `window.location.hash = '#section'`. (Or maybe we can with the `hashchange` event?)
34
- // - Other potential problem: would there be a conflict when the user wants to override the browser's default behavior? E.g. for smooth scrolling, or when using hashes for saving states of some fancy animations.
35
- // - Another alternative: we use the browser's scroll restoration mechanism (see `browserNativeScrollRestoration_enable()` below).
36
- // - Problem: not clear when to call `browserNativeScrollRestoration_disable()`/`browserNativeScrollRestoration_enable()`
37
- // - Other potential problem are inconsistencies between browsers: specification says that setting `window.history.scrollRestoration` only affects the current entry in the session history. But this seems to contradict what folks saying.
38
- // - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
39
- // - https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
40
- if (window.history.state === null) {
41
- // The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `initHistoryState()`.
42
- initHistoryState();
43
- globalObject.previousState = getState();
44
- }
45
- else {
46
- // If `history.state !== null` then it means that `popstate` was triggered by the user clicking on his browser's forward/backward history button.
47
- setScrollPosition(scrollTarget);
48
- }
49
- }
50
- else {
51
- await renderPageClientSide({ scrollTarget, isBackwardNavigation, isUserLandPushStateNavigation });
52
- }
53
- });
54
- }
55
- function getState() {
56
- return {
57
- urlWithoutHash: getCurrentUrl({ withoutHash: true }),
58
- historyState: getHistoryState()
59
- };
60
- }
61
- function updateState() {
62
- globalObject.previousState = getState();
63
- }