Skip to content

Commit

Permalink
Merge branch 'gh-7289' of github.com:sveltejs/kit into gh-7289
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Nov 28, 2022
2 parents 5f3a7aa + 3338a6d commit 8abb732
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 64 deletions.
2 changes: 1 addition & 1 deletion documentation/docs/30-advanced/30-link-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You can customise the behaviour of links with `data-sveltekit-*` attributes. The

### data-sveltekit-preload-data

Before the browser registers that the user has clicked on a link, we can detect that they've hovered the mouse over it (on desktop) or that a `touchstart` or `mousedown` event has happened. In both cases, we can make an educated guess that a `click` event is coming.
Before the browser registers that the user has clicked on a link, we can detect that they've hovered the mouse over it (on desktop) or that a `touchstart` or `mousedown` event was triggered. In both cases, we can make an educated guess that a `click` event is coming.

SvelteKit can use this information to get a head start on importing the code and fetching the page's data, which can give us an extra couple of hundred milliseconds — the difference between a user interface that feels laggy and one that feels snappy.

Expand Down
6 changes: 3 additions & 3 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { HttpError, Redirect } from '../control.js';
import { stores } from './singletons.js';
import { unwrap_promises } from '../../utils/promises.js';
import * as devalue from 'devalue';
import { INDEX_KEY, PRIORITY_PAGE, PRIORITY_VIEWPORT, SCROLL_KEY } from './constants.js';
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY } from './constants.js';

const routes = parse(nodes, server_loads, dictionary, matchers);

Expand Down Expand Up @@ -1236,11 +1236,11 @@ export function create_client({ target, base }) {

if (external) continue;

if (options.preload_code === PRIORITY_VIEWPORT) {
if (options.preload_code === PRELOAD_PRIORITIES.viewport) {
observer.observe(a);
}

if (options.preload_code === PRIORITY_PAGE) {
if (options.preload_code === PRELOAD_PRIORITIES.page) {
preload_code(/** @type {URL} */ (url).pathname);
}
}
Expand Down
11 changes: 7 additions & 4 deletions packages/kit/src/runtime/client/constants.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export const SCROLL_KEY = 'sveltekit:scroll';
export const INDEX_KEY = 'sveltekit:index';

export const PRIORITY_TAP = 1;
export const PRIORITY_HOVER = 2;
export const PRIORITY_VIEWPORT = 3;
export const PRIORITY_PAGE = 4;
export const PRELOAD_PRIORITIES = /** @type {const} */ ({
tap: 1,
hover: 2,
viewport: 3,
page: 4,
off: -1
});
85 changes: 45 additions & 40 deletions packages/kit/src/runtime/client/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { writable } from 'svelte/store';
import { assets } from '../paths.js';
import { version } from '../env.js';
import { PRIORITY_HOVER, PRIORITY_PAGE, PRIORITY_TAP, PRIORITY_VIEWPORT } from './constants.js';
import { PRELOAD_PRIORITIES } from './constants.js';

/* global __SVELTEKIT_APP_VERSION_FILE__, __SVELTEKIT_APP_VERSION_POLL_INTERVAL__ */

Expand All @@ -26,34 +26,54 @@ export function scroll_state() {

const warned = new WeakSet();

/** @typedef {keyof typeof valid_link_options} LinkOptionName */

const valid_link_options = /** @type {const} */ ({
'preload-code': ['', 'off', 'tap', 'hover', 'viewport', 'page'],
'preload-data': ['', 'off', 'tap', 'hover'],
noscroll: ['', 'off'],
reload: ['', 'off']
});

/**
* @template {LinkOptionName} T
* @param {Element} element
* @param {string} name
* @param {string | null} value
* @param {string[]} options
* @param {T} name
*/
function validate(element, name, value, options) {
if (warned.has(element)) return;
if (value === null) return;
if (!options.includes(value)) {
warned.add(element);
function link_option(element, name) {
const value = /** @type {typeof valid_link_options[T][number] | null} */ (
element.getAttribute(`data-sveltekit-${name}`)
);

return __SVELTEKIT_DEV__ ? validate_link_option(element, name, value) : value;
}

/**
* @template {LinkOptionName} T
* @template {typeof valid_link_options[T][number] | null} U
* @param {Element} element
* @param {T} name
* @param {U} value
*/
function validate_link_option(element, name, value) {
if (warned.has(element) || value === null) return /** @type {U} */ (null);

// @ts-expect-error - includes is dumb
if (!valid_link_options[name].includes(value)) {
console.error(
`Unexpected value for ${name} — should be one of ${options
`Unexpected value for ${name} — should be one of ${valid_link_options[name]
.map((option) => JSON.stringify(option))
.join(', ')}`,
element
);
}

return value;
}

/** @type {Record<string, number>} */
const levels = {
tap: PRIORITY_TAP,
hover: PRIORITY_HOVER,
viewport: PRIORITY_VIEWPORT,
page: PRIORITY_PAGE,
'': PRIORITY_HOVER,
off: -1
...PRELOAD_PRIORITIES,
'': PRELOAD_PRIORITIES.hover
};

/**
Expand All @@ -64,16 +84,16 @@ export function find_anchor(element, base) {
/** @type {HTMLAnchorElement | SVGAElement | undefined} */
let a;

/** @type {string | null} */
/** @type {typeof valid_link_options['noscroll'][number] | null} */
let noscroll = null;

/** @type {string | null} */
/** @type {typeof valid_link_options['preload-code'][number] | null} */
let preload_code = null;

/** @type {string | null} */
/** @type {typeof valid_link_options['preload-data'][number] | null} */
let preload_data = null;

/** @type {string | null} */
/** @type {typeof valid_link_options['reload'][number] | null} */
let reload = null;

while (element !== document.documentElement) {
Expand All @@ -83,25 +103,10 @@ export function find_anchor(element, base) {
}

if (a) {
if (preload_code === null) preload_code = element.getAttribute('data-sveltekit-preload-code');
if (preload_data === null) preload_data = element.getAttribute('data-sveltekit-preload-data');
if (noscroll === null) noscroll = element.getAttribute('data-sveltekit-noscroll');
if (reload === null) reload = element.getAttribute('data-sveltekit-reload');

if (__SVELTEKIT_DEV__) {
validate(element, 'data-sveltekit-preload-data', preload_data, ['', 'off', 'tap', 'hover']);
validate(element, 'data-sveltekit-preload-code', preload_code, [
'',
'off',
'tap',
'hover',
'viewport',
'page'
]);

validate(element, 'data-sveltekit-preload-data', noscroll, ['', 'off']);
validate(element, 'data-sveltekit-preload-data', reload, ['', 'off']);
}
if (preload_code === null) preload_code = link_option(element, 'preload-code');
if (preload_data === null) preload_data = link_option(element, 'preload-data');
if (noscroll === null) noscroll = link_option(element, 'noscroll');
if (reload === null) reload = link_option(element, 'reload');
}

// @ts-expect-error handle shadow roots
Expand Down
16 changes: 0 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8abb732

Please sign in to comment.