Skip to content

Commit

Permalink
feature: Replace sveltekit:* with valid HTML attributes like `data-…
Browse files Browse the repository at this point in the history
…sveltekit-*` (#6170)

* WIP: Replace `sveltekit:prefetch` with `data-sveltekit-prefetch` at build time.

* WIP: Use svelte-preprocess to replace values. Significant progress!

PoC works great if run from the user's svelte.config.js, but we need to extend the user config and still make it work. Currently it only works when run with the default svelte config loading.

* Improve attribute replacement and make it work even if app devs have custom preprocessing config.

Auto-reloading doesn't work though, so that needs to be fixed, along with regex specificity.

* WIP: Explore how to combine the svelte config by the user with the options needed by sveltekit.

* Improve type definition for `config.preprocess` to match what's used internally. Also allow object configs.

* Use API from vite-plugin-svelte to add internal SvelteKit preprocessing

Much cleaner solution, which also should be a tiny bit more performant than before.

* Cleanup

* Breaking: Rename sveltekit:prefetch to data-sveltekit-precfetch

* Breaking: Rename sveltekit:noscroll to data-sveltekit-noscroll

* Breaking: Rename sveltekit:reload to data-sveltekit-reload

* print console error for removed attributes in dev

* lint

* Update packages/kit/types/index.d.ts

* Update packages/kit/types/index.d.ts

* Create neat-pots-flash.md

Co-authored-by: Rich Harris <hello@rich-harris.dev>
  • Loading branch information
Greenheart and Rich-Harris committed Aug 30, 2022
1 parent 3d12949 commit 8e9839a
Show file tree
Hide file tree
Showing 14 changed files with 60 additions and 30 deletions.
6 changes: 6 additions & 0 deletions .changeset/neat-pots-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"create-svelte": patch
"@sveltejs/kit": patch
---

[breaking] Replace `sveltekit:*` with valid HTML attributes like `data-sveltekit-*`
18 changes: 9 additions & 9 deletions documentation/docs/09-a-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
title: Anchor options
---

### sveltekit:prefetch
### data-sveltekit-prefetch

SvelteKit uses code splitting to break your app into small chunks (one per route), ensuring fast startup times.

For _dynamic_ routes, such as our `src/routes/blog/[slug]/+page.svelte` example, that's not enough. In order to render the blog post, we need to fetch the data for it, and we can't do that until we know what `slug` is. In the worst case, that could cause lag as the browser waits for the data to come back from the server.

We can mitigate that by _prefetching_ the data. Adding a `sveltekit:prefetch` attribute to a link...
We can mitigate that by _prefetching_ the data. Adding a `data-sveltekit-prefetch` attribute to a link...

```html
<a sveltekit:prefetch href="blog/what-is-sveltekit">What is SvelteKit?</a>
<a data-sveltekit-prefetch href="blog/what-is-sveltekit">What is SvelteKit?</a>
```

...will cause SvelteKit to run the page's `load` function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the `click` event to trigger navigation. Typically, this buys us an extra couple of hundred milliseconds, which is the difference between a user interface that feels laggy, and one that feels snappy.
Expand All @@ -20,28 +20,28 @@ Note that prefetching will not work if the [`router`](/docs/page-options#router)

You can also programmatically invoke `prefetch` from `$app/navigation`.

### sveltekit:reload
### data-sveltekit-reload

By default, the SvelteKit runtime intercepts clicks on `<a>` elements and bypasses the normal browser navigation for relative (same-origin) URLs that match one of your page routes. We sometimes need to tell SvelteKit that certain links need to be handled by normal browser navigation. Examples of this might be linking to another page on your domain that's not part of your SvelteKit app or linking to an endpoint.

Adding a `sveltekit:reload` attribute to a link...
Adding a `data-sveltekit-reload` attribute to a link...

```html
<a sveltekit:reload href="path">Path</a>
<a data-sveltekit-reload href="path">Path</a>
```

...will cause browser to navigate via a full page reload when the link is clicked.

Links with a `rel="external"` attribute will receive the same treatment. In addition, they will be ignored during [prerendering](https://kit.svelte.dev/docs/page-options#prerender).

### sveltekit:noscroll
### data-sveltekit-noscroll

When navigating to internal links, SvelteKit mirrors the browser's default navigation behaviour: it will change the scroll position to 0,0 so that the user is at the very top left of the page (unless the link includes a `#hash`, in which case it will scroll to the element with a matching ID).

In certain cases, you may wish to disable this behaviour. Adding a `sveltekit:noscroll` attribute to a link...
In certain cases, you may wish to disable this behaviour. Adding a `data-sveltekit-noscroll` attribute to a link...

```html
<a href="path" sveltekit:noscroll>Path</a>
<a href="path" data-sveltekit-noscroll>Path</a>
```

...will prevent scrolling after the link is clicked.
4 changes: 2 additions & 2 deletions documentation/docs/80-migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ This caused problems and is no longer the case in SvelteKit. Instead, relative U

#### &lt;a&gt; attributes

- `sapper:prefetch` is now `sveltekit:prefetch`
- `sapper:noscroll` is now `sveltekit:noscroll`
- `sapper:prefetch` is now `data-sveltekit-prefetch`
- `sapper:noscroll` is now `data-sveltekit-noscroll`

### Endpoints

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li class:active={$page.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li>
<li class:active={$page.url.pathname === '/'}>
<a data-sveltekit-prefetch href="/">Home</a>
</li>
<li class:active={$page.url.pathname === '/about'}>
<a sveltekit:prefetch href="/about">About</a>
<a data-sveltekit-prefetch href="/about">About</a>
</li>
<li class:active={$page.url.pathname === '/todos'}>
<a sveltekit:prefetch href="/todos">Todos</a>
<a data-sveltekit-prefetch href="/todos">Todos</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<body>
<a href="https://external.com">https://external.com</a>
<a href="/wheee">/wheee</a>
<a sveltekit:prefetch href="/wheee2">/wheee</a>
<a href="/wheee3" sveltekit:prefetch>/wheee</a>
<a data-sveltekit-prefetch href="/wheee2">/wheee</a>
<a href="/wheee3" data-sveltekit-prefetch>/wheee</a>
<a href="/wheee4">/wheee</a>
</body>
</html>
1 change: 1 addition & 0 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ function kit() {
async config(config, config_env) {
vite_config_env = config_env;
svelte_config = await load_config();

env = get_env(svelte_config.kit.env, vite_config_env.mode);

// The config is created in build_server for SSR mode and passed inline
Expand Down
27 changes: 24 additions & 3 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ function update_scroll_positions(index) {
scroll_positions[index] = scroll_state();
}

/** @type {Record<string, true>} */
let warned_about_attributes = {};

function check_for_removed_attributes() {
const attrs = ['prefetch', 'noscroll', 'reload'];
for (const attr of attrs) {
if (document.querySelector(`[sveltekit\\:${attr}]`)) {
if (!warned_about_attributes[attr]) {
warned_about_attributes[attr] = true;
console.error(
`The sveltekit:${attr} attribute has been replaced with data-sveltekit-${attr}`
);
}
}
}
}

/**
* @param {{
* target: Element;
Expand Down Expand Up @@ -271,6 +288,8 @@ export function create_client({ target, base, trailing_slash }) {
};
root.$set(navigation_result.props);
tick().then(() => (console.warn = warn));

check_for_removed_attributes();
} else {
root.$set(navigation_result.props);
}
Expand Down Expand Up @@ -369,6 +388,8 @@ export function create_client({ target, base, trailing_slash }) {
hydrate: true
});
console.warn = warn;

check_for_removed_attributes();
} else {
root = new Root({
target,
Expand Down Expand Up @@ -1138,7 +1159,7 @@ export function create_client({ target, base, trailing_slash }) {
/** @param {Event} event */
const trigger_prefetch = (event) => {
const a = find_anchor(event);
if (a && a.href && a.hasAttribute('sveltekit:prefetch')) {
if (a && a.href && a.hasAttribute('data-sveltekit-prefetch')) {
prefetch(get_href(a));
}
};
Expand Down Expand Up @@ -1195,7 +1216,7 @@ export function create_client({ target, base, trailing_slash }) {
if (
a.hasAttribute('download') ||
rel.includes('external') ||
a.hasAttribute('sveltekit:reload')
a.hasAttribute('data-sveltekit-reload')
) {
return;
}
Expand All @@ -1222,7 +1243,7 @@ export function create_client({ target, base, trailing_slash }) {

navigate({
url,
scroll: a.hasAttribute('sveltekit:noscroll') ? scroll_state() : null,
scroll: a.hasAttribute('data-sveltekit-noscroll') ? scroll_state() : null,
keepfocus: false,
redirect_chain: [],
details: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
<a href="http://localhost:{$page.url.searchParams.get('port')}">elsewhere</a>
<a href="/static.json">static.json</a>

<a href="/routing/b" sveltekit:reload>b</a>
<a href="/routing/b" data-sveltekit-reload>b</a>

<div class="hydrate-test" />
2 changes: 1 addition & 1 deletion packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ test.describe('Routing', () => {
expect(await page.textContent('body')).toBe('ok');
});

test('does not attempt client-side navigation to links with sveltekit:reload', async ({
test('does not attempt client-side navigation to links with data-sveltekit-reload', async ({
baseURL,
page
}) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<a sveltekit:prefetch href="/path-base/prefetching/prefetched">click me</a>
<a data-sveltekit-prefetch href="/path-base/prefetching/prefetched">click me</a>
2 changes: 1 addition & 1 deletion packages/kit/types/ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ declare module '$app/navigation' {
* 1. ensuring that the code for the page is loaded, and
* 2. calling the page's load function with the appropriate options.
*
* This is the same behaviour that SvelteKit triggers when the user taps or mouses over an `<a>` element with `sveltekit:prefetch`.
* This is the same behaviour that SvelteKit triggers when the user taps or mouses over an `<a>` element with `data-sveltekit-prefetch`.
* If the next navigation is to `href`, the values returned from load will be used, making navigation instantaneous.
* Returns a Promise that resolves when the prefetch is complete.
*
Expand Down
6 changes: 3 additions & 3 deletions sites/kit.svelte.dev/src/lib/docs/Contents.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
{#each contents as section}
<li>
<a
sveltekit:prefetch
data-sveltekit-prefetch
class="section"
class:active={section.path === path}
href={section.path}
Expand All @@ -95,7 +95,7 @@
{#each section.sections as subsection}
<li>
<a
sveltekit:prefetch
data-sveltekit-prefetch
class="subsection"
class:active={subsection.path === path}
href={subsection.path}
Expand All @@ -109,7 +109,7 @@
{#each subsection.sections as subsection}
<li>
<a
sveltekit:prefetch
data-sveltekit-prefetch
class="nested subsection"
class:active={subsection.path === path}
href={subsection.path}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
{#each results as result, i}
<li>
<a
sveltekit:prefetch
data-sveltekit-prefetch
href={result.href}
on:click={() => dispatch('select', { href: result.href })}
data-has-node={result.node ? true : undefined}
Expand Down
6 changes: 3 additions & 3 deletions sites/kit.svelte.dev/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
of an SPA
</p>

<a sveltekit:prefetch href="/docs" class="cta">read the docs</a>
<a data-sveltekit-prefetch href="/docs" class="cta">read the docs</a>
</div>

<div slot="three">
Expand All @@ -50,7 +50,7 @@
support and more
</p>

<a sveltekit:prefetch href="/docs" class="cta">read the docs</a>
<a data-sveltekit-prefetch href="/docs" class="cta">read the docs</a>
</div>

<div class="description" slot="what">
Expand All @@ -77,7 +77,7 @@ cd my-app
npm install
npm run dev -- --open</code
></pre>
<a sveltekit:prefetch href="/docs" class="cta">get started</a>
<a data-sveltekit-prefetch href="/docs" class="cta">get started</a>
</div>
</Blurb>
</div>
Expand Down

0 comments on commit 8e9839a

Please sign in to comment.