svelte: New component `root` property may throw errors
Read this comment first
The reason why this occurs is that you are likely trying to use a pre-compiled (to JS) component that was compiled with a different Svelte version than the one you use, which is not supported. See this comment for more info and solutions: https://github.com/sveltejs/svelte/issues/6584#issuecomment-1019578529
Describe the bug
I recently experienced issues due to new root property in several svelte plugins.
It seems that this line causes issues: https://github.com/sveltejs/svelte/commit/5cfefeb6e72f8085e418150b644cdc4b4f6f260d#diff-da9bae4e28c441de5ba3a074e30775fe69109100b3d921ad8f2592d93cd67b7f
It seems that a null check for parent_component variable is missing at that point.
on_mount: [],
on_destroy: [],
on_disconnect: [],
before_update: [],
after_update: [],
context: new Map(parent_component ? parent_component.$$.context : options.context || []), // Here, there is a null check for parent_component variable
// everything else
callbacks: blank_object(),
dirty,
skip_bound: false,
root: options.target || parent_component.$$.root // Here there is no check for parent_component variable
Reproduction
This suddenly occured on certain svelte plugins.
Logs
No response
System Info
System:
OS: Linux 5.8 Debian GNU/Linux 10 (buster) 10 (buster)
CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
Memory: 517.19 MB / 7.47 GB
Container: Yes
Shell: 5.0.3 - /bin/bash
Binaries:
Node: 16.0.0 - ~/.n/bin/node
npm: 7.10.0 - ~/.n/bin/npm
npmPackages:
svelte: ^3.31.2 => 3.38.3
webpack: ^5.16.0 => 5.44.0
Severity
blocking an upgrade
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 22
- Comments: 53 (7 by maintainers)
Commits related to this issue
- [fix]: downgraded svelte to fix stuff. see: https://github.com/sveltejs/svelte/issues/6584#issue-953948572 — committed to piptouque/marcelle by deleted user 3 years ago
- Revert svelte back to v3.39.0 Fixes a bug in compiled components, probably related to sveltejs/svelte#6584 — committed to marcellejs/marcelle by JulesFrancoise 3 years ago
- go back to svelte 3.39 see https://github.com/sveltejs/svelte/issues/6584 — committed to xavhan/svelte-vitamin by deleted user 3 years ago
- downgraded to svelte 3.39.0 b/c https://github.com/sveltejs/svelte/issues/6584 ?? root component issue — committed to livingtongues/living-dictionaries by jacob-8 3 years ago
- chore(force): Downgrade svelte version to fix root issue https://github.com/sveltejs/svelte/issues/6584 — committed to untemps/svelte-palette by untemps 3 years ago
- chore(force): Downgrade svelte version to fix root issue (#13) https://github.com/sveltejs/svelte/issues/6584 — committed to untemps/svelte-palette by untemps 3 years ago
- Implement Svelte patch for components that can’t be server-side rendered See issue: https://github.com/sveltejs/svelte/issues/6584 And PR: https://github.com/sveltejs/svelte/pull/6646/files — committed to small-tech/nodekit by aral 2 years ago
- see sveltejs/svelte#6584 — committed to yapcheahshen/NOVAS by yapcheahshen 2 years ago
The problem here is instantiating a component compiled with Svelte version X inside an app compiled with Svelte version Y in a declarative way.
The following is not guaranteed to work:
The following will work:
If using a component from a library, ensure that an uncompiled version exists and is used by your build tool. SvelteKit’s
packagecommand ensures this for example.Try downgrading svelte version until it works again. Version
3.39.0worked fine for me.On 30. 7. 2021 12:01, nullbio wrote:
https://github.com/sveltejs/svelte/pull/6646 What about this pr? Its open for month now
Hello,
I do have the same issue in my app while trying to test a component which contains an “if” statement and a mock module. I did not have the issue back when I was using Svelte 3.35.0. I tried to upgrade yesterday to 3.43.0, but did not succeed. I had to rollback to 3.39.0.
To ease a bit the debug, here’s a simplified repo to reproduce the issue: https://github.com/gcruchon/tests/tree/main/svelte-null-parent-component
I’m using last version of all libraries (svelte, jest, svelte-jester, babel, testing-library, …). I used the svelte template and just added the bug (i.e. testing a mocked “Link” within an “if” statement)
Feel free to comment if I missed something.
Thanks. Clearing my package-lock.json, node_modules, and adding
"svelte": "3.39.0",to my package.json seems to have worked. Didn’t think it would because in my build svelte is a dependency of esbuild-svelte, but I suppose in the land of node it enforces a version for sub-dependencies if you declare one explicitly. News to me. Just leaving this here for anyone else who needs it and is new to all of this like I am.Actually, I could resolve this issue with a correct rollup config in my library project. I defined all svelte related stuff as external and excluded from resolve, so it is fetched from within the project that is using my components fro the library. My rollup config looks as follows:
Apparently works fine, since all svelte stuff gets provided by the build system of the application using the component.
I’ve been racking my brain for the last 3 hours trying to figure out why my app suddenly started exploding… Eventually managed to find this issue. Is there a simple fix to reverting this bug so I can continue development until it’s patched? I’m using esbuild-svelte which is pulling in a broken version I guess, so I can’t just define an older version of svelte in my package.json as far as I’m aware?
For others trying to Google this issue, the console output for Chrome is:
Uncaught (in promise) TypeError: Cannot read property '$$' of nullAnd for Firefox:
Uncaught (in promise) TypeError: parent_component is nullThat’s why there exists the
sveltekit packagefeature.Library authors should ideally use this feature to create the package. Authors can use SCSS, TypeScript and other language variants and in the end normal JavaScript and CSS components will be generated that can be consumed by any other Svelte project.
Here is an example of a TypesScript demo package: https://github.com/ivanhofer/svienna-meetup-package-demo. You can run
npm run packageand see the exported files in thepackagefolder. All files are beeing converted to normal JavaScript versions.If you are using a library that doesn’t get published in the right way, you could open an issue and let the authors know that this feature exists.
@Conduitry
Microfrontends are the use case 😃
The change in #6646 would prevent this, yes.
Of course the other issues would still exist, but if you use svelte this way, you might be aware of them.
Experiencing the same issue. I had svelte app, which includes npm svelte component and it throws this error:
This is my simplified code snippet:
Thanks for this! I’m trying to use shared components, with webpack module federation. Tried with <svelte:component />, but I also get error like others (parent_component).
This is my working RemoteButton component (should add some error handling):
I am still getting this error, even though I made sure the components were precompiled with the same version of svelte as the one the app uses (
3.53.1). The components were compiled usingesbuildvia theesbuild-svelte&svelte-preprocess. AFAIK,esbuild-sveltedeclaressvelteaspeerDependencysince0.7.0, and I am using0.7.3, so it is definitely using the correct svelte version to compile the components.For context, I am trying to develop a desktop application that has a plugin system that can extend the application’s functionality, and one part of it is that plugins can export svelte components that can then be used in the application itself. The application imports the compiled svelte files via the
import()syntax. The imported component is then consumed via<svelte:component>. Each<svelte:component>is rendered inside of adiv, so I would expect svelte to be able to pick up theparent_componentcorrectly.yes, definitely
not really, because you can still consume compiled components manually, using the
new Component()syntaxit is very useful to have, i.e. a well-crafted component that can operate standalone
This also occurs when sharing components with webpacks module federation. (In the current version of svelte, older versions work). An example is here: https://github.com/micschwarz/svelte-module-federation
Thanks @atomcat1978, set svelte (and svelte/internal) as a external librairie fix the build issue on client side 😃 Potatoes for everyone ! 🥔
@pateketrueke What if someone uses a svelte component written in typescript, but the project is using pure JS? Then one would have to add typescript just because of the component used? Feels like an overhead definetely.
I finally have a solution… building svelte/internal as a separate module and treating
svelteandsvelte/internaldependencies as external and pointing them to the module. That makes the internal svelte logic to be shared for all the components. I updated the repo I created for reproduction of one of the issues I had with the pre-bundled components …so you can have a look.I second @pateketrueke’s opinion. See https://github.com/tjinauyeung/svelte-forms-lib/issues/169#issuecomment-1145736546 for a discussion.
@Conduitry There should be a big warning in the Svelte doc that using pre-bundled Svelte components is not supported. It’s a blocker for our project and probably for some others too.
@dummdidumm Hey Simon, thank you, that does indeed work. I’m going to see how I can incorporate checking if the source exists for a component and using that in my loader’s resolution. I’m assuming that’s what the
svelteentries in the package.json files are for. Appreciate your help.It’s odd because I’m using a custom resolver in my esbuild to ensure that all Svelte references get mapped to the single instance of Svelte that’s in my app. And I’m still seeing this error (see above).
@bluwy Cannot duplicate in the REPL neither. But it was happening. It was quite hard to replicate back then. But since when I tried
3.43.1it worked for me since then.A possibly related post on Reddit: https://www.reddit.com/r/sveltejs/comments/pjo902/svelte_microfrontend_module_federation_bug/?utm_medium=android_app&utm_source=share