vike 0.4.198 → 0.4.199-commit-6991a96
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.
- package/dist/cjs/node/plugin/plugins/fileEnv.js +3 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
- package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/client/client-routing-runtime/history.d.ts +8 -7
- package/dist/esm/client/client-routing-runtime/history.js +65 -46
- package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
- package/dist/esm/client/client-routing-runtime/index.js +1 -0
- package/dist/esm/client/client-routing-runtime/initClientRouter.js +4 -4
- package/dist/esm/client/client-routing-runtime/initOnPopState.d.ts +29 -0
- package/dist/esm/client/client-routing-runtime/initOnPopState.js +78 -0
- package/dist/esm/client/client-routing-runtime/prefetch.d.ts +1 -2
- package/dist/esm/client/client-routing-runtime/prefetch.js +21 -3
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +2 -13
- package/dist/esm/node/plugin/plugins/fileEnv.js +3 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
- package/dist/esm/shared/page-configs/Config.d.ts +7 -7
- package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/package.json +1 -1
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +0 -4
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +0 -63
|
@@ -22,6 +22,9 @@ function fileEnv() {
|
|
|
22
22
|
return;
|
|
23
23
|
if (skip(id))
|
|
24
24
|
return;
|
|
25
|
+
// For `.vue` files: https://github.com/vikejs/vike/issues/1912#issuecomment-2394981475
|
|
26
|
+
if (id.endsWith('?direct'))
|
|
27
|
+
id = id.slice(0, -1 * '?direct'.length);
|
|
25
28
|
const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
|
|
26
29
|
(0, utils_js_1.assert)(moduleInfo);
|
|
27
30
|
const importers = Array.from(moduleInfo.importers)
|
|
@@ -88,7 +88,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
|
|
|
88
88
|
metafile: true,
|
|
89
89
|
bundle: true
|
|
90
90
|
};
|
|
91
|
-
|
|
91
|
+
const pointerImports = {};
|
|
92
92
|
options.plugins = [
|
|
93
93
|
// Determine whether an import should be:
|
|
94
94
|
// - A pointer import
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
export {
|
|
2
|
-
type
|
|
3
|
-
timestamp
|
|
4
|
-
scrollPosition
|
|
5
|
-
triggeredBy
|
|
1
|
+
export { enhanceHistoryState, getHistoryState, pushHistory, type ScrollPosition, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
|
+
type StateVikeEnhanced = {
|
|
3
|
+
timestamp: number;
|
|
4
|
+
scrollPosition: null | ScrollPosition;
|
|
5
|
+
triggeredBy: 'user' | 'vike' | 'browser';
|
|
6
6
|
_isVikeEnhanced: true;
|
|
7
7
|
};
|
|
8
8
|
type ScrollPosition = {
|
|
9
9
|
x: number;
|
|
10
10
|
y: number;
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
declare function
|
|
12
|
+
type StateNotInitialized = null | undefined | Partial<StateVikeEnhanced> | StateVikeEnhanced;
|
|
13
|
+
declare function enhanceHistoryState(): void;
|
|
14
|
+
declare function getHistoryState(): StateNotInitialized;
|
|
14
15
|
declare function saveScrollPosition(): void;
|
|
15
16
|
declare function pushHistory(url: string, overwriteLastHistoryEntry: boolean): void;
|
|
16
17
|
declare function monkeyPatchHistoryPushState(): void;
|
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { enhanceHistoryState, getHistoryState, pushHistory, saveScrollPosition, monkeyPatchHistoryPushState };
|
|
2
2
|
import { assert, assertUsage, hasProp, isObject } from './utils.js';
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
3
|
+
// `window.history.state === null` when:
|
|
4
|
+
// - The very first render
|
|
5
|
+
// - Click on `<a href="#some-hash" />`
|
|
6
|
+
// - `location.hash = 'some-hash'`
|
|
7
|
+
function enhanceHistoryState() {
|
|
8
|
+
const stateNotInitialized = window.history.state;
|
|
9
|
+
if (isVikeEnhanced(stateNotInitialized))
|
|
10
|
+
return;
|
|
11
|
+
const stateVikeEnhanced = enhance(stateNotInitialized);
|
|
12
|
+
replaceHistoryState(stateVikeEnhanced);
|
|
13
|
+
}
|
|
14
|
+
function enhance(stateNotInitialized) {
|
|
15
|
+
const timestamp = getTimestamp();
|
|
16
|
+
const scrollPosition = getScrollPosition();
|
|
17
|
+
const triggeredBy = 'browser';
|
|
18
|
+
let stateVikeEnhanced;
|
|
19
|
+
if (!stateNotInitialized) {
|
|
20
|
+
stateVikeEnhanced = {
|
|
21
|
+
timestamp,
|
|
22
|
+
scrollPosition,
|
|
23
|
+
triggeredBy,
|
|
24
|
+
_isVikeEnhanced: true
|
|
25
|
+
};
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
else {
|
|
28
|
+
// State information may be incomplete if `window.history.state` is set by an old Vike version. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
|
|
29
|
+
stateVikeEnhanced = {
|
|
30
|
+
timestamp: stateNotInitialized.timestamp ?? timestamp,
|
|
31
|
+
scrollPosition: stateNotInitialized.scrollPosition ?? scrollPosition,
|
|
32
|
+
triggeredBy: stateNotInitialized.triggeredBy ?? triggeredBy,
|
|
33
|
+
_isVikeEnhanced: true
|
|
34
|
+
};
|
|
30
35
|
}
|
|
36
|
+
assert(isVikeEnhanced(stateVikeEnhanced));
|
|
37
|
+
return stateVikeEnhanced;
|
|
38
|
+
}
|
|
39
|
+
function getState_alreadyEnhanced() {
|
|
40
|
+
const state = getHistoryState();
|
|
41
|
+
assert(isVikeEnhanced(state));
|
|
42
|
+
return state;
|
|
31
43
|
}
|
|
32
44
|
function getHistoryState() {
|
|
33
|
-
const state = window.history.state
|
|
34
|
-
assertState(state);
|
|
45
|
+
const state = window.history.state;
|
|
35
46
|
return state;
|
|
36
47
|
}
|
|
37
48
|
function getScrollPosition() {
|
|
@@ -43,29 +54,22 @@ function getTimestamp() {
|
|
|
43
54
|
}
|
|
44
55
|
function saveScrollPosition() {
|
|
45
56
|
const scrollPosition = getScrollPosition();
|
|
46
|
-
const state =
|
|
57
|
+
const state = getState_alreadyEnhanced();
|
|
47
58
|
replaceHistoryState({ ...state, scrollPosition });
|
|
48
59
|
}
|
|
49
60
|
function pushHistory(url, overwriteLastHistoryEntry) {
|
|
50
61
|
if (!overwriteLastHistoryEntry) {
|
|
51
62
|
const timestamp = getTimestamp();
|
|
52
|
-
pushHistoryState({
|
|
63
|
+
pushHistoryState({
|
|
64
|
+
timestamp,
|
|
65
|
+
// I don't remember why I set it to `null`, maybe because setting it now would be too early? (Maybe there is a delay between renderPageClientSide() is finished and the browser updating the scroll position.) Anyways, it seems like autoSaveScrollPosition() is enough.
|
|
66
|
+
scrollPosition: null,
|
|
67
|
+
triggeredBy: 'vike',
|
|
68
|
+
_isVikeEnhanced: true
|
|
69
|
+
}, url);
|
|
53
70
|
}
|
|
54
71
|
else {
|
|
55
|
-
replaceHistoryState(
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function assertState(state) {
|
|
59
|
-
assert(isObject(state));
|
|
60
|
-
if ('timestamp' in state) {
|
|
61
|
-
const { timestamp } = state;
|
|
62
|
-
assert(typeof timestamp === 'number');
|
|
63
|
-
}
|
|
64
|
-
if ('scrollPosition' in state) {
|
|
65
|
-
const { scrollPosition } = state;
|
|
66
|
-
if (scrollPosition !== null) {
|
|
67
|
-
assert(hasProp(scrollPosition, 'x', 'number') && hasProp(scrollPosition, 'y', 'number'));
|
|
68
|
-
}
|
|
72
|
+
replaceHistoryState(getState_alreadyEnhanced(), url);
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
function replaceHistoryState(state, url) {
|
|
@@ -89,9 +93,24 @@ function monkeyPatchHistoryPushState() {
|
|
|
89
93
|
triggeredBy: 'user',
|
|
90
94
|
...stateOriginal
|
|
91
95
|
};
|
|
96
|
+
assert(isVikeEnhanced(stateEnhanced));
|
|
92
97
|
return pushStateOriginal(stateEnhanced, ...rest);
|
|
93
98
|
};
|
|
94
99
|
}
|
|
95
100
|
function isVikeEnhanced(state) {
|
|
96
|
-
|
|
101
|
+
const yes = isObject(state) && '_isVikeEnhanced' in state;
|
|
102
|
+
if (yes)
|
|
103
|
+
assertStateVikeEnhanced(state);
|
|
104
|
+
return yes;
|
|
105
|
+
}
|
|
106
|
+
function assertStateVikeEnhanced(state) {
|
|
107
|
+
assert(isObject(state));
|
|
108
|
+
assert(hasProp(state, '_isVikeEnhanced', 'true'));
|
|
109
|
+
// TODO/eventually: remove assert() below to save client-side KBs
|
|
110
|
+
assert(hasProp(state, 'timestamp', 'number'));
|
|
111
|
+
assert(hasProp(state, 'scrollPosition'));
|
|
112
|
+
if (state.scrollPosition !== null) {
|
|
113
|
+
assert(hasProp(state, 'scrollPosition', 'object'));
|
|
114
|
+
assert(hasProp(state.scrollPosition, 'x', 'number') && hasProp(state.scrollPosition, 'y', 'number'));
|
|
115
|
+
}
|
|
97
116
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { navigate, reload } from './navigate.js';
|
|
2
2
|
export { prefetch } from './prefetch.js';
|
|
3
|
+
export { onPopState } from './initOnPopState.js';
|
|
3
4
|
export { PROJECT_VERSION as version } from './utils.js';
|
|
4
5
|
import type { PageContextBuiltInClientWithClientRouting } from '../../shared/types.js';
|
|
5
6
|
/** @deprecated
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { initClientRouter };
|
|
2
2
|
import { assert } from './utils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { enhanceHistoryState, monkeyPatchHistoryPushState } from './history.js';
|
|
4
4
|
import { getRenderCount, renderPageClientSide } from './renderPageClientSide.js';
|
|
5
|
-
import {
|
|
5
|
+
import { initOnPopState } from './initOnPopState.js';
|
|
6
6
|
import { initOnLinkClick } from './initOnLinkClick.js';
|
|
7
7
|
import { setupNativeScrollRestoration } from './scrollRestoration.js';
|
|
8
8
|
import { autoSaveScrollPosition } from './setScrollPosition.js';
|
|
@@ -29,9 +29,9 @@ async function renderFirstPage() {
|
|
|
29
29
|
}
|
|
30
30
|
function initHistoryAndScroll() {
|
|
31
31
|
setupNativeScrollRestoration();
|
|
32
|
-
|
|
32
|
+
enhanceHistoryState();
|
|
33
33
|
autoSaveScrollPosition();
|
|
34
34
|
monkeyPatchHistoryPushState();
|
|
35
35
|
// Handle back-/forward navigation
|
|
36
|
-
|
|
36
|
+
initOnPopState();
|
|
37
37
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { initOnPopState };
|
|
2
|
+
export { updateState };
|
|
3
|
+
export { onPopState };
|
|
4
|
+
declare function initOnPopState(): void;
|
|
5
|
+
type Listener = (arg: {
|
|
6
|
+
_experimental: {
|
|
7
|
+
previousState: ReturnType<typeof getState>;
|
|
8
|
+
};
|
|
9
|
+
}) => undefined | boolean;
|
|
10
|
+
/** Control client-side navigation.
|
|
11
|
+
*
|
|
12
|
+
* https://vike.dev/onPopState
|
|
13
|
+
*/
|
|
14
|
+
declare function onPopState(listener: Listener): void;
|
|
15
|
+
declare function getState(): {
|
|
16
|
+
urlWithoutHash: string;
|
|
17
|
+
historyState: {
|
|
18
|
+
timestamp: number;
|
|
19
|
+
scrollPosition: null | import("./history.js").ScrollPosition;
|
|
20
|
+
triggeredBy: "user" | "vike" | "browser";
|
|
21
|
+
_isVikeEnhanced: true;
|
|
22
|
+
} | Partial<{
|
|
23
|
+
timestamp: number;
|
|
24
|
+
scrollPosition: null | import("./history.js").ScrollPosition;
|
|
25
|
+
triggeredBy: "user" | "vike" | "browser";
|
|
26
|
+
_isVikeEnhanced: true;
|
|
27
|
+
}> | null | undefined;
|
|
28
|
+
};
|
|
29
|
+
declare function updateState(): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export { initOnPopState };
|
|
2
|
+
export { updateState };
|
|
3
|
+
export { onPopState };
|
|
4
|
+
import { assert, getCurrentUrl, getGlobalObject } from './utils.js';
|
|
5
|
+
import { enhanceHistoryState, getHistoryState } from './history.js';
|
|
6
|
+
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
7
|
+
import { setScrollPosition } from './setScrollPosition.js';
|
|
8
|
+
const globalObject = getGlobalObject('initOnPopState.ts', { previousState: getState(), listeners: [] });
|
|
9
|
+
function initOnPopState() {
|
|
10
|
+
// - The popstate event is trigged upon:
|
|
11
|
+
// - Back-/forward navigation.
|
|
12
|
+
// - By user clicking on his browser's back-/forward navigation (or using a shortcut)
|
|
13
|
+
// - By JavaScript: `history.back()` / `history.forward()`
|
|
14
|
+
// - URL hash change.
|
|
15
|
+
// - Click on `<a href="#some-hash" />`
|
|
16
|
+
// - 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)
|
|
17
|
+
// - `location.hash = 'some-hash'`
|
|
18
|
+
// - 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
|
|
19
|
+
window.addEventListener('popstate', async () => {
|
|
20
|
+
const { previousState } = globalObject;
|
|
21
|
+
const currentState = getState();
|
|
22
|
+
globalObject.previousState = currentState;
|
|
23
|
+
const scrollTarget = currentState.historyState?.scrollPosition || undefined;
|
|
24
|
+
const isHashNavigation = currentState.urlWithoutHash === previousState.urlWithoutHash;
|
|
25
|
+
const isBackwardNavigation = !currentState.historyState?.timestamp || !previousState.historyState?.timestamp
|
|
26
|
+
? null
|
|
27
|
+
: currentState.historyState.timestamp < previousState.historyState.timestamp;
|
|
28
|
+
// - `history.state === null` when:
|
|
29
|
+
// - Click on `<a href="#some-hash" />` (note that Vike's `initOnLinkClick()` handler skips hash links)
|
|
30
|
+
// - `location.hash = 'some-hash'`
|
|
31
|
+
// - `history.state !== null` when `popstate` was triggered by the user clicking on his browser's forward/backward history button.
|
|
32
|
+
let isHashNavigationNew = isHashNavigation && window.history.state === null;
|
|
33
|
+
if (window.history.state === null) {
|
|
34
|
+
assert(isHashNavigation);
|
|
35
|
+
// The browser already scrolled to `#${hash}` => the current scroll position is the right one => we save it with `enhanceHistoryState()`.
|
|
36
|
+
enhanceHistoryState();
|
|
37
|
+
globalObject.previousState = getState();
|
|
38
|
+
}
|
|
39
|
+
// 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:
|
|
40
|
+
// - Alternative: we use `window.history.scrollRestoration = 'auto'`
|
|
41
|
+
// - Problem: I don't think it's possbible to set `window.history.scrollRestoration = 'auto'` only for hash navigation and not for non-hash navigations?
|
|
42
|
+
// - 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.
|
|
43
|
+
// - Specification: https://html.spec.whatwg.org/multipage/history.html#the-history-interface
|
|
44
|
+
// - Practice: https://stackoverflow.com/questions/70188241/history-scrollrestoration-manual-doesnt-prevent-safari-from-restoring-scrol
|
|
45
|
+
// - Alternative: we completely take over hash navigation and reproduce the browser's native behavior upon hash navigation.
|
|
46
|
+
// - By using the `hashchange` event.
|
|
47
|
+
// - 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.
|
|
48
|
+
if (isHashNavigation) {
|
|
49
|
+
if (!isHashNavigationNew) {
|
|
50
|
+
setScrollPosition(scrollTarget);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let abort;
|
|
55
|
+
globalObject.listeners.forEach((listener) => {
|
|
56
|
+
abort || (abort = listener({ _experimental: { previousState } }));
|
|
57
|
+
});
|
|
58
|
+
if (abort)
|
|
59
|
+
return;
|
|
60
|
+
await renderPageClientSide({ scrollTarget, isBackwardNavigation });
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** Control client-side navigation.
|
|
64
|
+
*
|
|
65
|
+
* https://vike.dev/onPopState
|
|
66
|
+
*/
|
|
67
|
+
function onPopState(listener) {
|
|
68
|
+
globalObject.listeners.push(listener);
|
|
69
|
+
}
|
|
70
|
+
function getState() {
|
|
71
|
+
return {
|
|
72
|
+
urlWithoutHash: getCurrentUrl({ withoutHash: true }),
|
|
73
|
+
historyState: getHistoryState()
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function updateState() {
|
|
77
|
+
globalObject.previousState = getState();
|
|
78
|
+
}
|
|
@@ -28,9 +28,8 @@ declare function populatePageContextPrefetchCache(pageContext: PageContextForPre
|
|
|
28
28
|
*
|
|
29
29
|
* @param url - The URL of the page you want to prefetch.
|
|
30
30
|
*/
|
|
31
|
-
declare function prefetch(url: string,
|
|
31
|
+
declare function prefetch(url: string, options_?: {
|
|
32
32
|
pageContext?: boolean;
|
|
33
|
-
staticAssets?: boolean;
|
|
34
33
|
}): Promise<void>;
|
|
35
34
|
declare function addLinkPrefetchHandlers(): void;
|
|
36
35
|
declare function initLinkPrefetchHandlers(): void;
|
|
@@ -93,7 +93,18 @@ function getResultMaxAge() {
|
|
|
93
93
|
*
|
|
94
94
|
* @param url - The URL of the page you want to prefetch.
|
|
95
95
|
*/
|
|
96
|
-
async function prefetch(url,
|
|
96
|
+
async function prefetch(url,
|
|
97
|
+
/* TODO/pageContext-prefetch
|
|
98
|
+
options?: {
|
|
99
|
+
pageContext?: boolean
|
|
100
|
+
staticAssets?: boolean
|
|
101
|
+
}
|
|
102
|
+
*/
|
|
103
|
+
options_) {
|
|
104
|
+
const options = {
|
|
105
|
+
staticAssets: true,
|
|
106
|
+
pageContext: options_?.pageContext ?? false
|
|
107
|
+
};
|
|
97
108
|
assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
|
|
98
109
|
showStackTrace: true
|
|
99
110
|
});
|
|
@@ -115,6 +126,7 @@ async function prefetch(url, options) {
|
|
|
115
126
|
})(),
|
|
116
127
|
(async () => {
|
|
117
128
|
if (options?.pageContext !== false) {
|
|
129
|
+
assertUsage(isBrilloutDocpress(), "prefetching pageContext isn't supported yet");
|
|
118
130
|
const resultMaxAge = typeof options?.pageContext === 'number' ? options.pageContext : null;
|
|
119
131
|
await prefetchPageContextFromServerHooks(pageContextLink, resultMaxAge);
|
|
120
132
|
}
|
|
@@ -183,8 +195,14 @@ async function prefetchOnEvent(linkTag, event) {
|
|
|
183
195
|
prefetchSettings = getPrefetchSettings(pageContextCurrent, linkTag);
|
|
184
196
|
}
|
|
185
197
|
else {
|
|
186
|
-
|
|
187
|
-
|
|
198
|
+
if (isBrilloutDocpress()) {
|
|
199
|
+
// TODO/pageContext-prefetch: remove this dirty hack used by @brillout/docpress and, instead, use Vike's default if pageContextCurrent isn't defined yet.
|
|
200
|
+
prefetchSettings = { staticAssets: 'hover', pageContext: Infinity };
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// TODO/pageContext-prefetch: consider pageContextLink
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
188
206
|
}
|
|
189
207
|
// Check again in case DOM was manipulated since last check
|
|
190
208
|
if (skipLink(linkTag))
|
|
@@ -12,8 +12,6 @@ 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;
|
|
17
15
|
isClientSideNavigation?: boolean;
|
|
18
16
|
};
|
|
19
17
|
declare function renderPageClientSide(renderArgs: RenderArgs): Promise<void>;
|
|
@@ -15,7 +15,7 @@ import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError,
|
|
|
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 './
|
|
18
|
+
import { updateState } from './initOnPopState.js';
|
|
19
19
|
import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
|
|
20
20
|
import { getErrorPageId } from '../../shared/error-page.js';
|
|
21
21
|
import { setPageContextCurrent } from './getPageContextCurrent.js';
|
|
@@ -30,15 +30,11 @@ const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
|
|
|
30
30
|
})());
|
|
31
31
|
const { firstRenderStartPromise } = globalObject;
|
|
32
32
|
async function renderPageClientSide(renderArgs) {
|
|
33
|
-
const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0,
|
|
33
|
+
const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isClientSideNavigation = true } = renderArgs;
|
|
34
34
|
let { scrollTarget } = renderArgs;
|
|
35
35
|
const { previousPageContext } = globalObject;
|
|
36
36
|
addLinkPrefetchHandlers_unwatch();
|
|
37
37
|
const { isRenderOutdated, setHydrationCanBeAborted, isFirstRender } = getIsRenderOutdated();
|
|
38
|
-
// Note that pageContext.isHydration isn't equivalent to isFirstRender
|
|
39
|
-
// - Thus pageContext.isHydration isn't equivalent to !pageContext.isClientSideNavigation
|
|
40
|
-
// - `pageContext.isHydration === !isFirstRender && !isErrorPage`
|
|
41
|
-
assert(isClientSideNavigation === !isFirstRender);
|
|
42
38
|
assertNoInfiniteAbortLoop(pageContextsFromRewrite.length, redirectCount);
|
|
43
39
|
if (globalObject.clientRoutingIsDisabled) {
|
|
44
40
|
redirectHard(urlOriginal);
|
|
@@ -121,13 +117,6 @@ async function renderPageClientSide(renderArgs) {
|
|
|
121
117
|
redirectHard(urlOriginal);
|
|
122
118
|
return;
|
|
123
119
|
}
|
|
124
|
-
const isSamePage = pageContextFromRoute.pageId &&
|
|
125
|
-
previousPageContext?.pageId &&
|
|
126
|
-
pageContextFromRoute.pageId === previousPageContext.pageId;
|
|
127
|
-
if (isUserLandPushStateNavigation && isSamePage) {
|
|
128
|
-
// Skip's Vike's rendering; let the user handle the navigation
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
120
|
// TODO/eventually: create helper assertPageContextFromHook()
|
|
132
121
|
assert(!('urlOriginal' in pageContextFromRoute));
|
|
133
122
|
objectAssign(pageContext, pageContextFromRoute);
|
|
@@ -17,6 +17,9 @@ function fileEnv() {
|
|
|
17
17
|
return;
|
|
18
18
|
if (skip(id))
|
|
19
19
|
return;
|
|
20
|
+
// For `.vue` files: https://github.com/vikejs/vike/issues/1912#issuecomment-2394981475
|
|
21
|
+
if (id.endsWith('?direct'))
|
|
22
|
+
id = id.slice(0, -1 * '?direct'.length);
|
|
20
23
|
const moduleInfo = viteDevServer.moduleGraph.getModuleById(id);
|
|
21
24
|
assert(moduleInfo);
|
|
22
25
|
const importers = Array.from(moduleInfo.importers)
|
|
@@ -83,7 +83,7 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
|
|
|
83
83
|
metafile: true,
|
|
84
84
|
bundle: true
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
const pointerImports = {};
|
|
87
87
|
options.plugins = [
|
|
88
88
|
// Determine whether an import should be:
|
|
89
89
|
// - A pointer import
|
|
@@ -34,6 +34,7 @@ export type { KeepScrollPosition };
|
|
|
34
34
|
import type { PrefetchSetting, PrefetchStaticAssets } from '../../client/client-routing-runtime/prefetch/PrefetchSetting.js';
|
|
35
35
|
import type { ConfigDefinition } from '../../node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js';
|
|
36
36
|
import type { DocumentHtml } from '../../node/runtime/html/renderHtml.js';
|
|
37
|
+
import type { InjectFilterEntry } from '../../types/index.js';
|
|
37
38
|
import type { ConfigVikeUserProvided } from '../ConfigVike.js';
|
|
38
39
|
import type { Vike, VikePackages } from '../VikeNamespace.js';
|
|
39
40
|
import type { HooksTimeoutProvidedByUser } from '../hooks/getHook.js';
|
|
@@ -190,17 +191,16 @@ type OnRenderClientSync = (pageContext: PageContextClient) => void;
|
|
|
190
191
|
*
|
|
191
192
|
* https://vike.dev/onRenderHtml
|
|
192
193
|
*/
|
|
193
|
-
type OnRenderHtmlAsync = (pageContext: PageContextServer) => Promise<
|
|
194
|
-
documentHtml: DocumentHtml;
|
|
195
|
-
pageContext: OnRenderHtmlPageContextReturn | (() => Promise<OnRenderHtmlPageContextReturn> | OnRenderHtmlPageContextReturn);
|
|
196
|
-
}>;
|
|
194
|
+
type OnRenderHtmlAsync = (pageContext: PageContextServer) => Promise<OnRenderHtmlReturn>;
|
|
197
195
|
/** Hook called when page is rendered to HTML on the server-side.
|
|
198
196
|
*
|
|
199
197
|
* https://vike.dev/onRenderHtml
|
|
200
198
|
*/
|
|
201
|
-
type OnRenderHtmlSync = (pageContext: PageContextServer) =>
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
type OnRenderHtmlSync = (pageContext: PageContextServer) => OnRenderHtmlReturn;
|
|
200
|
+
type OnRenderHtmlReturn = DocumentHtml | {
|
|
201
|
+
injectFilter?: (assets: InjectFilterEntry[]) => void;
|
|
202
|
+
documentHtml?: DocumentHtml;
|
|
203
|
+
pageContext?: OnRenderHtmlPageContextReturn | (() => Promise<OnRenderHtmlPageContextReturn> | OnRenderHtmlPageContextReturn);
|
|
204
204
|
};
|
|
205
205
|
type OnRenderHtmlPageContextReturn = Partial<Vike.PageContext & {
|
|
206
206
|
/** See https://vike.dev/streaming */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PROJECT_VERSION: "0.4.
|
|
1
|
+
export declare const PROJECT_VERSION: "0.4.199-commit-6991a96";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Automatically updated by @brillout/release-me
|
|
2
|
-
export const PROJECT_VERSION = '0.4.
|
|
2
|
+
export const PROJECT_VERSION = '0.4.199-commit-6991a96';
|
package/package.json
CHANGED
|
@@ -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
|
-
}
|