Closed ghost closed 7 months ago
Yeah, this is because things are being built with different copies of Svelte's internal runtime. The parent-child relationship isn't correctly maintained between components that are compiled and bundled separately, and so the context is seen as undefined.
The proper way to go about this would be to use the svelte
key in the child components' package.json files to point to the original .svelte source and specify 'svelte'
in your mainFields
webpack config (see https://github.com/sveltejs/svelte-loader). This way all of the components are compiled and bundled together, with a single copy of the internals.
It's probably be possible to make this work even when bundling against different copies of the internals (by making the internals use special global variables to store this, rather than variables local to the module), but I don't think this is a use we want to cater to. There are a number of reasons to just have one copy of the Svelte internals. (Both bundle size concerns, and several features that simply won't work otherwise.) So I would consider this more of a gap in the docs (Questions related to this have come up several times.) than a bug in the code.
That makes sense, and thank you for the explanation. I had a feeling this would be the issue.
Unfortunately in my use case I can't bundle all components up at the same time because I don't always know which components will exist on the site, so I will look for other ways around this if the props
route becomes too unmaintainable.
In the case of the browser it's simple, because I can just attach the store to the window
instead of using the context API. My only reason for trying to use the context API was because I needed a way to share a new store for each new request on the server-side for SSR.
At first I though that maybe there would be a way to explicitly pass a context to a child component, but if this is a use case you may not want to cater to then I suppose there would be no reason to allow for that to happen in the first place.
This is solved by https://github.com/sveltejs/svelte/issues/3671#issuecomment-541277465
I'll leave this issue open since it's got the docs
tag, but I just wanted to point out the comment that solved the problem for me as that's likely the best thing to document.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Closing — as noted, the solution here is to avoid prebundling Svelte (not just svelte/internal
, which no longer exists in Svelte 5, but all svelte/*
imports)
Edit: I've found this issue too, which I think looks like the same problem I'm describing here: https://github.com/sveltejs/svelte/issues/3422
Describe the bug I'm trying to build a system that loads external standalone components at runtime, and I want to use the
getContext
andsetContext
functions to share a store between all of the components.I'm using webpack to build the main application which contains an
App
component that serves as the root of the application, and then I'm using a completely separate project to build another external standalone component (both an SSR version and a DOM versions), which I then load in at runtime usingrequire
on the Node server-side, and a<script>
tag on the client-side within the mainApp
component.The external standalone component does load and render correctly, however within the component any calls to
getContext
returnundefined
.I'm not familiar with the Svelte codebase, but I assume this is due to the standalone component being built as a separate project and getting its own versions of the context related variables/functions at build time, rather than sharing the same variables etc. from the parent.
I assume this is a bug, but if I'm just doing something wrong please let me know.
Logs No logs other than
getContext
printingundefined
in the child standalone component.To Reproduce
<script>
tag or something)<svelte:component this={MyStandaloneComponent} />
getContext
in the standalone component returnundefined
because it (I think) doesn't have the same contextExpected behavior I expect to see
getContext
in the standalone component return data from the same context as the parent component from the main application.Information about your Svelte project:
Severity I can get around this issue by passing the store I want to share as a prop to the child standalone component, but it's not ideal, especially in large projects where the same store may need to be shared amonst hundreds of standalone components.
This problem is more one of code maintenance/tech debt in my specific case, so I'd much prefer to have
getContext
work correctly where the standalone child component should inherit the context from the parent component in the main application.Although in my specifc case I can easily work around the issue using props instead, I can imagine that for applications sharing much more than a simple store this could be prohibitive, so I'd say it's a fairly severe issue.
Additional context I've tried various build options using Webpack, such as changing
libraryTarget
, or changing Svelte build flags, like changingcustomElements
totrue
orfalse
.No matter the build options this problem always seems to occur.