mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-23 15:41:32 +00:00
implement session/preload on client
This commit is contained in:
@@ -3,6 +3,7 @@ import { stores } from '@sapper/internal';
|
|||||||
import Root from '__ROOT__';
|
import Root from '__ROOT__';
|
||||||
import { preload as root_preload } from '__ROOT_PRELOAD__';
|
import { preload as root_preload } from '__ROOT_PRELOAD__';
|
||||||
import ErrorComponent from '__ERROR__';
|
import ErrorComponent from '__ERROR__';
|
||||||
|
import { writable } from 'svelte/store.mjs';
|
||||||
import {
|
import {
|
||||||
Target,
|
Target,
|
||||||
ScrollPosition,
|
ScrollPosition,
|
||||||
@@ -18,6 +19,8 @@ import goto from './goto';
|
|||||||
// injected at build time
|
// injected at build time
|
||||||
declare const __IGNORE__, __COMPONENTS__, __PAGES__, __SAPPER__;
|
declare const __IGNORE__, __COMPONENTS__, __PAGES__, __SAPPER__;
|
||||||
|
|
||||||
|
export const initial_data = typeof __SAPPER__ !== 'undefined' && __SAPPER__;
|
||||||
|
|
||||||
const ignore = __IGNORE__;
|
const ignore = __IGNORE__;
|
||||||
export const components: ComponentLoader[] = __COMPONENTS__;
|
export const components: ComponentLoader[] = __COMPONENTS__;
|
||||||
export const routes: Route[] = __PAGES__;
|
export const routes: Route[] = __PAGES__;
|
||||||
@@ -28,6 +31,26 @@ let current_token: {};
|
|||||||
let root_preloaded: Promise<any>;
|
let root_preloaded: Promise<any>;
|
||||||
let current_branch = [];
|
let current_branch = [];
|
||||||
|
|
||||||
|
const session = writable(initial_data && initial_data.session);
|
||||||
|
|
||||||
|
let $session;
|
||||||
|
let session_dirty: boolean;
|
||||||
|
|
||||||
|
session.subscribe(async value => {
|
||||||
|
$session = value;
|
||||||
|
|
||||||
|
if (!ready) return;
|
||||||
|
session_dirty = true;
|
||||||
|
|
||||||
|
const target = select_target(new URL(location.href));
|
||||||
|
|
||||||
|
const token = current_token = {};
|
||||||
|
const { redirect, props, branch } = await hydrate_target(target);
|
||||||
|
if (token !== current_token) return; // a secondary navigation happened while we were loading
|
||||||
|
|
||||||
|
await render(redirect, branch, props, target.page);
|
||||||
|
});
|
||||||
|
|
||||||
export let prefetching: {
|
export let prefetching: {
|
||||||
href: string;
|
href: string;
|
||||||
promise: Promise<{ redirect?: Redirect, data?: any }>;
|
promise: Promise<{ redirect?: Redirect, data?: any }>;
|
||||||
@@ -56,8 +79,6 @@ export function set_cid(n) {
|
|||||||
cid = n;
|
cid = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initial_data = typeof __SAPPER__ !== 'undefined' && __SAPPER__;
|
|
||||||
|
|
||||||
const _history = typeof history !== 'undefined' ? history : {
|
const _history = typeof history !== 'undefined' ? history : {
|
||||||
pushState: (state: any, title: string, href: string) => {},
|
pushState: (state: any, title: string, href: string) => {},
|
||||||
replaceState: (state: any, title: string, href: string) => {},
|
replaceState: (state: any, title: string, href: string) => {},
|
||||||
@@ -137,13 +158,32 @@ export async function navigate(target: Target, id: number, noscroll?: boolean, h
|
|||||||
const { redirect, props, branch } = await loaded;
|
const { redirect, props, branch } = await loaded;
|
||||||
if (token !== current_token) return; // a secondary navigation happened while we were loading
|
if (token !== current_token) return; // a secondary navigation happened while we were loading
|
||||||
|
|
||||||
if (redirect) return goto(redirect.location, { replaceState: true });
|
await render(redirect, branch, props, target.page);
|
||||||
|
|
||||||
await render(branch, props, target.page, scroll_history[id], noscroll, hash);
|
|
||||||
if (document.activeElement) document.activeElement.blur();
|
if (document.activeElement) document.activeElement.blur();
|
||||||
|
|
||||||
|
if (!noscroll) {
|
||||||
|
let scroll = scroll_history[id];
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
// scroll is an element id (from a hash), we need to compute y.
|
||||||
|
const deep_linked = document.querySelector(hash);
|
||||||
|
|
||||||
|
if (deep_linked) {
|
||||||
|
scroll = {
|
||||||
|
x: 0,
|
||||||
|
y: deep_linked.getBoundingClientRect().top
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function render(branch: any[], props: any, page: Page, scroll: ScrollPosition, noscroll: boolean, hash: string) {
|
scroll_history[cid] = scroll;
|
||||||
|
if (scroll) scrollTo(scroll.x, scroll.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function render(redirect: Redirect, branch: any[], props: any, page: Page) {
|
||||||
|
if (redirect) return goto(redirect.location, { replaceState: true });
|
||||||
|
|
||||||
stores.page.set(page);
|
stores.page.set(page);
|
||||||
stores.preloading.set(false);
|
stores.preloading.set(false);
|
||||||
|
|
||||||
@@ -165,31 +205,15 @@ async function render(branch: any[], props: any, page: Page, scroll: ScrollPosit
|
|||||||
props: {
|
props: {
|
||||||
Root,
|
Root,
|
||||||
props,
|
props,
|
||||||
session: __SAPPER__.session
|
session
|
||||||
},
|
},
|
||||||
hydrate: true
|
hydrate: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noscroll) {
|
|
||||||
if (hash) {
|
|
||||||
// scroll is an element id (from a hash), we need to compute y.
|
|
||||||
const deep_linked = document.querySelector(hash);
|
|
||||||
|
|
||||||
if (deep_linked) {
|
|
||||||
scroll = {
|
|
||||||
x: 0,
|
|
||||||
y: deep_linked.getBoundingClientRect().top
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scroll_history[cid] = scroll;
|
|
||||||
if (scroll) scrollTo(scroll.x, scroll.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_branch = branch;
|
current_branch = branch;
|
||||||
ready = true;
|
ready = true;
|
||||||
|
session_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function hydrate_target(target: Target): Promise<{
|
export async function hydrate_target(target: Target): Promise<{
|
||||||
@@ -221,7 +245,7 @@ export async function hydrate_target(target: Target): Promise<{
|
|||||||
path: page.path,
|
path: page.path,
|
||||||
query: page.query,
|
query: page.query,
|
||||||
params: {}
|
params: {}
|
||||||
});
|
}, $session);
|
||||||
}
|
}
|
||||||
|
|
||||||
let branch;
|
let branch;
|
||||||
@@ -231,7 +255,7 @@ export async function hydrate_target(target: Target): Promise<{
|
|||||||
if (!part) return null;
|
if (!part) return null;
|
||||||
|
|
||||||
const segment = segments[i];
|
const segment = segments[i];
|
||||||
if (current_branch[i] && current_branch[i].segment === segment) return current_branch[i];
|
if (!session_dirty && current_branch[i] && current_branch[i].segment === segment) return current_branch[i];
|
||||||
|
|
||||||
const { default: Component, preload } = await load_component(components[part.i]);
|
const { default: Component, preload } = await load_component(components[part.i]);
|
||||||
|
|
||||||
@@ -242,7 +266,7 @@ export async function hydrate_target(target: Target): Promise<{
|
|||||||
path: page.path,
|
path: page.path,
|
||||||
query: page.query,
|
query: page.query,
|
||||||
params: part.params ? part.params(target.match) : {}
|
params: part.params ? part.params(target.match) : {}
|
||||||
})
|
}, $session)
|
||||||
: {};
|
: {};
|
||||||
} else {
|
} else {
|
||||||
preloaded = initial_data.preloaded[i + 1];
|
preloaded = initial_data.preloaded[i + 1];
|
||||||
|
|||||||
Reference in New Issue
Block a user