-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
__layout.svelte may run twice after browser reload in dev #2130
Comments
I can reproduce using the following <script context="module">
console.log("Layout module.");
</script>
<script>
console.log("Layout instance.");
</script> Start dev server as normal. Change something in This issue seems to affect hot reloading of the dev server, as it disappears after restarting the dev server. |
#2154 (comment) may have identified the cause of the issue. All the components (layout, error, and pages) in const c = [
() => import("..\\..\\..\\src\\routes\\__layout.svelte"),
() => import("..\\components\\error.svelte"),
() => import("..\\..\\..\\src\\routes\\index.svelte"),
// ...
];
export const routes = [
// src/routes/index.svelte
[/^\/$/, [c[0], c[2]], [c[1]]],
// ...
]; But the export const fallback = [c[0](), c[1]()]; Is there a reason why |
I've traced the origin of the diff --git a/packages/kit/src/core/create_app/index.js b/packages/kit/src/core/create_app/index.js
index ea84e023..b5a1137c 100644
--- a/packages/kit/src/core/create_app/index.js
+++ b/packages/kit/src/core/create_app/index.js
@@ -102,7 +102,7 @@ function generate_client_manifest(manifest_data, base) {
export const routes = ${routes};
- export const fallback = [c[0](), c[1]()];
+ export const fallback = [c[0], c[1]];
`);
}
diff --git a/packages/kit/src/runtime/client/renderer.js b/packages/kit/src/runtime/client/renderer.js
index 4b1fdd10..7d9cbfb1 100644
--- a/packages/kit/src/runtime/client/renderer.js
+++ b/packages/kit/src/runtime/client/renderer.js
@@ -60,7 +60,7 @@ function initial_fetch(resource, opts) {
export class Renderer {
/** @param {{
* Root: CSRComponent;
- * fallback: [CSRComponent, CSRComponent];
+ * fallback: [() => CSRComponent, () => CSRComponent];
* target: Node;
* session: any;
* host: string;
@@ -708,7 +708,7 @@ export class Renderer {
};
const node = await this._load_node({
- module: await this.fallback[0],
+ module: await this.fallback[0](),
page,
context: {}
});
@@ -718,7 +718,7 @@ export class Renderer {
await this._load_node({
status,
error,
- module: await this.fallback[1],
+ module: await this.fallback[1](),
page,
context: (node && node.loaded && node.loaded.context) || {}
}) As far as I can tell that works (running |
I have tried the same and I can concur that every test was passing before and after the changes were made. But I was waiting to see if that was the right approach before raising a PR. Should I take this up and raise a PR? |
Turns out there is a reason. According to #1356 (comment) it's deliberate to have the fallback components (the root layout and error components) imported during initial load, even if they're not used, precisely because they are fallback components. If something goes wrong in the process of loading a page, one of the likely reasons why it went wrong is a network failure, in which case loading the error components will fail too if they aren't already in the user's browser. That is why the root layout and error components are imported as soon as possible, so that they will be in memory in the user's browser and available to use without any further network traffic. Which means that if the network goes down five seconds after the user loads your site's first page, there's at least something that Svelte-Kit can display to inform them that the site isn't working right. Therefore, this behavior is unlikely to change, and the only real fix to this issue is going to be to add a note to the documentation saying "Don't put side effects in the root layout module script, as they might be run twice, and/or run when you don't expect them to run." |
@rmunn, This issue is not about not keeping Could you at least explain these:
|
I don't understand your question very well without the exact context. I'm not sure if you're referring to the abnormal log mentioned in this issue, or my text about app level imports mentioned in #2169 If you inspect the pictures above, you'll notice that all logs are from If you're asking if an import could be evaluated twice during development, I already experienced this not a long time ago server side when trying to create a middleware for realtime communication. At first, I imported it from |
So let me try to explain what I observed, I have disabled JS source maps in chrome dev tools to avoid any confusion in viewing the source files. Let me break this down into two parts:
BeforeWhen we see the network calls made, we can see AfterNow after force updating the It is fetched once from the And you can see from the above screenshot that the second So back to the question I was asking before, There are two import statements for |
@anudeepreddy, I started to receive similar logs as yours (with query strings) after using an updated chrome browser. Trying to understand how the development server is pushing the HMR updates to browser, I created a new file <!-- src/routes/foo.svelte -->
<div>foo</div>
You already discovered what's causing this issue. In the second case, one of the imports is appending a query string with a timestamp, causing the two imports to be evaluated independently as two different modules. |
I have the same behavior while running dev mode but the layout gets only reinitialized (a second time) after the first change of navigation. Lucky I found this issue...I was getting mad since I thought I am causing the problem somehow. And i just realized it only happened in dev mode. |
I've been struggling with the same issue. Honestly I think it is quite an important bug, which really influences my productivity with Sveltekit as every item or component that gets initialized globally in __layout, is added multiple times. I have this kind of setup in more then 50% of my projects and to really check if the site is working I always need to build it which is quite annoying. If anybody knows a workaround for development i would be very thankful. |
This issue happens to me as well. One of a few issues that makes SvelteKit is not that mature enough (this is stated in docs). Thanks for the comments above that made me understand the problem. Honestly I think this is a deal breaker for v1.0. |
In my experience this issue is caused by prefetch. Wish there was a way to disable prefetching in dev mode EDIT: I just ran |
@Bandit |
Yeah it seems that doing something that restarts the server fixes the problem temporarily. You can simulate this by CMD+C'ing the server and starting it again and the problem goes away for a while. |
Same bug here :) |
Should be fixed by #4891 |
This is really annoying. Since I only have one element in my EDIT: Just realized that components inside the layout can also display the same behavior. Now I don't have duplicate layouts, but I do have two views at the same time. It's really unsustainable to develop with this bug. <script>
import { onMount, tick } from 'svelte';
onMount(async () => {
await tick();
if (document.querySelectorAll('[data-layout]').length > 1) {
document.querySelector('[data-layout]').remove();
}
});
</script>
<div data-layout="true">
<slot />
</div> |
@ReneMoraales wish I'd thought of doing that 9 months ago! ha ha |
faced the same issue, i have two part of view rendered twice. i can provide picture if someone will be intrested. effect can be achieved only on refreshing page with refresh button and if we go to page through advertising company in search))) |
Describe the bug
This issue only affects the context script for
src/routes/__layout.svelte
. Other layout files are not affected, and #1214 is different.At first, everything works fine across browser reloads, updating some other files isn't a problem at all. But updating the top level layout file, or any of it's imported dependencies (components or modules) will trigger this issue, to cause the context script to run twice when I reload the browser's tab. Clearing the browser's cache won't help until I reload the development server.
Before the update
After the update (notice the abnormal additional log changing positions)
Reproduction
npm init svelte@next __layout-ctx-run-twice
npm run dev
localhost:3000
, all the logs are logged once respecting the same order across reloads, and they're all coming from__layout.svelte? [sm]
src/routes/__layout.svelte
, then reload the browser tab.__layout.svelte? [sm]
as the other logs, and the abnormal one is coming from__layout.svelte
Logs
No response
System Info
Severity
annoyance
Additional Information
Tested using both Chrome and Firefox.
The text was updated successfully, but these errors were encountered: