Skip to content

Commit

Permalink
don't warn about window.fetch during hydration (#5041)
Browse files Browse the repository at this point in the history
* failing test for #5031

* move fetch logic into separate module - fixes #5031

* changeset

* remove .only
  • Loading branch information
Rich-Harris authored May 23, 2022
1 parent d5cf5e0 commit 948c980
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 64 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-scissors-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

don't warn about window.fetch during hydration
37 changes: 5 additions & 32 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
find_anchor,
get_base_uri,
get_href,
initial_fetch,
notifiable_store,
scroll_state
} from './utils.js';
import * as fetcher from './fetcher.js';
import { parse } from './parse.js';

import Root from '__GENERATED__/root.svelte';
Expand Down Expand Up @@ -48,33 +48,6 @@ function update_scroll_positions(index) {
scroll_positions[index] = scroll_state();
}

const fetch = window.fetch;
let loading = 0;

if (import.meta.env.DEV) {
let can_inspect_stack_trace = false;

const check_stack_trace = async () => {
const stack = /** @type {string} */ (new Error().stack);
can_inspect_stack_trace = stack.includes('check_stack_trace');
};

check_stack_trace();

window.fetch = (input, init) => {
const url = input instanceof Request ? input.url : input.toString();
const stack = /** @type {string} */ (new Error().stack);

const heuristic = can_inspect_stack_trace ? stack.includes('load_node') : loading;
if (heuristic) {
console.warn(
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/loading#input-fetch`
);
}
return fetch(input, init);
};
}

/**
* @param {{
* target: Element;
Expand Down Expand Up @@ -621,7 +594,7 @@ export function create_client({ target, session, base, trailing_slash }) {
add_dependency(normalized);

// prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be normalized
return started ? fetch(normalized, init) : initial_fetch(requested, init);
return started ? fetcher.native(normalized, init) : fetcher.initial(requested, init);
},
status: status ?? null,
error: error ?? null
Expand All @@ -640,10 +613,10 @@ export function create_client({ target, session, base, trailing_slash }) {

if (import.meta.env.DEV) {
try {
loading += 1;
fetcher.increment();
loaded = await module.load.call(null, load_input);
} finally {
loading -= 1;
fetcher.decrement();
}
} else {
loaded = await module.load.call(null, load_input);
Expand Down Expand Up @@ -731,7 +704,7 @@ export function create_client({ target, session, base, trailing_slash }) {
const is_shadow_page = has_shadow && i === a.length - 1;

if (is_shadow_page) {
const res = await fetch(
const res = await fetcher.native(
`${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`,
{
headers: {
Expand Down
59 changes: 59 additions & 0 deletions packages/kit/src/runtime/client/fetcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { hash } from '../hash.js';

let loading = 0;

export const native = window.fetch;

export function increment() {
loading += 1;
}

export function decrement() {
loading -= 1;
}

if (import.meta.env.DEV) {
let can_inspect_stack_trace = false;

const check_stack_trace = async () => {
const stack = /** @type {string} */ (new Error().stack);
can_inspect_stack_trace = stack.includes('check_stack_trace');
};

check_stack_trace();

window.fetch = (input, init) => {
const url = input instanceof Request ? input.url : input.toString();
const stack = /** @type {string} */ (new Error().stack);

const heuristic = can_inspect_stack_trace ? stack.includes('load_node') : loading;
if (heuristic) {
console.warn(
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/loading#input-fetch`
);
}
return native(input, init);
};
}

/**
* @param {RequestInfo} resource
* @param {RequestInit} [opts]
*/
export function initial(resource, opts) {
const url = JSON.stringify(typeof resource === 'string' ? resource : resource.url);

let selector = `script[sveltekit\\:data-type="data"][sveltekit\\:data-url=${url}]`;

if (opts && typeof opts.body === 'string') {
selector += `[sveltekit\\:data-body="${hash(opts.body)}"]`;
}

const script = document.querySelector(selector);
if (script && script.textContent) {
const { body, ...init } = JSON.parse(script.textContent);
return Promise.resolve(new Response(body, init));
}

return native(resource, opts);
}
23 changes: 0 additions & 23 deletions packages/kit/src/runtime/client/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { writable } from 'svelte/store';
import { hash } from '../hash.js';
import { assets } from '../paths.js';

/** @param {HTMLDocument} doc */
Expand Down Expand Up @@ -115,25 +114,3 @@ export function create_updated_store() {
check
};
}

/**
* @param {RequestInfo} resource
* @param {RequestInit} [opts]
*/
export function initial_fetch(resource, opts) {
const url = JSON.stringify(typeof resource === 'string' ? resource : resource.url);

let selector = `script[sveltekit\\:data-type="data"][sveltekit\\:data-url=${url}]`;

if (opts && typeof opts.body === 'string') {
selector += `[sveltekit\\:data-body="${hash(opts.body)}"]`;
}

const script = document.querySelector(selector);
if (script && script.textContent) {
const { body, ...init } = JSON.parse(script.textContent);
return Promise.resolve(new Response(body, init));
}

return fetch(resource, opts);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script context="module">
/** @type {import('./index').Load} */
export async function load({ url, fetch }) {
const res = await fetch(`${url.origin}/load/window-fetch/data.json`);
const { answer } = await res.json();
return {
props: { answer }
};
}
</script>

<script>
/** @type {number} */
export let answer;
</script>

<h1>{answer}</h1>
27 changes: 18 additions & 9 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1506,21 +1506,30 @@ test.describe.parallel('Load', () => {
});

test('using window.fetch causes a warning', async ({ page, javaScriptEnabled }) => {
const warnings = [];
if (javaScriptEnabled && process.env.DEV) {
const warnings = [];

page.on('console', (msg) => {
if (msg.type() === 'warning') {
warnings.push(msg.text());
}
});
page.on('console', (msg) => {
if (msg.type() === 'warning') {
warnings.push(msg.text());
}
});

await page.goto('/load/window-fetch');
expect(await page.textContent('h1')).toBe('42');
await page.goto('/load/window-fetch/incorrect');
expect(await page.textContent('h1')).toBe('42');

if (javaScriptEnabled && process.env.DEV) {
expect(warnings).toContain(
'Loading http://localhost:3000/load/window-fetch/data.json using `window.fetch`. For best results, use the `fetch` that is passed to your `load` function: https://kit.svelte.dev/docs/loading#input-fetch'
);

warnings.length = 0;

await page.goto('/load/window-fetch/correct');
expect(await page.textContent('h1')).toBe('42');

expect(warnings).not.toContain(
'Loading http://localhost:3000/load/window-fetch/data.json using `window.fetch`. For best results, use the `fetch` that is passed to your `load` function: https://kit.svelte.dev/docs/loading#input-fetch'
);
}
});
});
Expand Down

0 comments on commit 948c980

Please sign in to comment.