kit: lifecycle-methods (onMount/onDestroy) are failing when called inside an installed package in dev

Describe the bug

If I try to use onMount()/ onDestroy() inside an installed 3rd-party-module, it errors in dev-mode but works in prod/preview with Error: Function called outside component initialization.

The exact same code works flawlessly if copied into a local module (see repro @ https://github.com/benbender/sveltekit-lifecycle-repro-ts/blob/master/src/routes/index.svelte#L2).

Noticed the problem at first while tinkering with a port of react-query/core to svelte, noticed it again today while looking into sswr. So it’s not a problem of a particular package.

Update: In next.146 the bug can be fixed by adding the problematic package to vite.optimizeDeps.exclude. Example in https://github.com/benbender/sveltekit-lifecycle-repro-ts/tree/workaround

Reproduction

  1. clone + install https://github.com/benbender/sveltekit-lifecycle-repro-ts
  2. run in dev and switch between the installed and the local copy of the code
  3. see it fail

Logs

proxy.js:15 [HMR][Svelte] Unrecoverable error in <Index>: next update will trigger a full reload
logError @ proxy.js:15
Proxy<Index> @ proxy.js:370
create_if_block_2 @ root.svelte? [sm]:38
create_default_slot @ root.svelte? [sm]:37
create_slot @ index.mjs?v=6a55c099:69
create_fragment @ layout.svelte:21
init @ index.mjs?v=6a55c099:1799
Layout @ layout.svelte:97
createProxiedComponent @ svelte-hooks.js:245
ProxyComponent @ proxy.js:239
Proxy<Layout> @ proxy.js:339
create_fragment @ root.svelte? [sm]:36
init @ index.mjs?v=6a55c099:1799
Root @ root.svelte? [sm]:16
createProxiedComponent @ svelte-hooks.js:245
ProxyComponent @ proxy.js:239
Proxy<Root> @ proxy.js:339
_init @ start.js:681
start @ start.js:563
async function (async)
start @ start.js:515
start @ start.js:1141
(anonymous) @ (index):15
index.mjs:931 Uncaught (in promise) Error: Function called outside component initialization
    at get_current_component (index.mjs:931)
    at onMount (index.mjs:938)
    at l.useSvelte (index.js:1)
    at useSWR (index.js:1)
    at instance (index.svelte? [sm]:4)
    at init (index.mjs?v=6a55c099:1784)
    at new Routes (index.svelte? [sm]:9)
    at createProxiedComponent (svelte-hooks.js:245)
    at new ProxyComponent (proxy.js:239)
    at new Proxy<Index> (proxy.js:339)

System Info

System:
    OS: macOS 11.4
    CPU: (8) arm64 Apple M1
    Memory: 148.09 MB / 8.00 GB
    Shell: 3.3.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 16.6.0 - /opt/homebrew/bin/node
    Yarn: 1.22.10 - /opt/homebrew/bin/yarn
    npm: 7.19.1 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 92.0.4515.131
    Firefox: 90.0.2
    Safari: 14.1.1
  npmPackages:
    @sveltejs/kit: next => 1.0.0-next.146
    svelte: ^3.34.0 => 3.42.1

Severity

serious, as I think at least any slightly advanced data-fetching-library for svelte will need to hook into the component lifecycle. At the moment those libraries are practically unusable for endusers as they won’t be able to develop with them. There are for sure more usecases where this will be a problem, but this is mine 😉

Additional Information

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 19 (8 by maintainers)

Most upvoted comments

sswr does not set the “svelte” field in its package.json https://github.com/ConsoleTVs/sswr/blob/master/package.json which is probably fine as it doesn’t export svelte components. But because of that it isn’t detected by the fix i linked above. For now you can add it to kit.vite.optimizeDeps.exclude and kit.vite.ssr.noExternal in your svelte.config.js

@dominikg @benbender Thanks for the hard work here, I will add this note to the docs and wait for official fixes! Great work to both of you!

@dominikg I’m happy to report that this issue is fixed with the release. Awesome work! Thank you!

Note: Once https://github.com/sveltejs/vite-plugin-svelte/pull/137 is released for vite-plugin-svelte and upgraded in SvelteKit, the workaround re optimizeDeps.exclude is not needed anymore.

@frederikhors not really as this issue isn’t about sswr and the underlying problem isn’t fixed.

It could be closed instead as a bug in vite or rollup-plugin-svelte. As I’m not sure how to handle this further and if this needs to be tracked here, I would like to delegate the decision to @dominikg, who is much deeper into the topic 😃

@dominikg Thanks for the explanation. You are probably right 👍

thats the thing, there are no components in sswr. It is a utility library with a peer dependency on svelte. Unfortunately vite optimizer currently does not deduplicate svelte correctly, so for it to work you have to exclude libraries from optimization until vite is fixed. Thats being worked on right now. Your copy to src solution basically bypassed the optimizer and therefore worked. sswr doesn’t need to distribute the source of its utility.

In case you want to dive into the rabbit hole https://github.com/sveltejs/vite-plugin-svelte/issues/125 https://github.com/vitejs/vite/discussions/4230#discussioncomment-1128519

Seeing this as a blocker in the ‘sswr’ pkg