What not to do when publishing a Svelte component locally
- Using local dependency like
"your-package": "file:../some-path"ornpm linkdoesn't work with Svelte because you will have duplicated Svelte runtimes. - What works is to use
npm packand thennpm install <path_to_tgz> - Bundlers look for Svelte runtime in the
node_modulesfolder (orpackage.json; I didn't dive deeper) that belongs to the component folder's ancestor tree. If there are 2node_modulesfolders involved, then there will be duplicated Svelte runtimes. - Having duplicated Svelte runtimes would result in obscure errors like:
Cannot read properties of undefined (reading 'call')withinget_first_childorUncaught TypeError: Cannot read properties of null (reading 'f')onparent_effect.f
I was just stuck at publishing a Svelte component locally for almost a whole day.
I was looking to publish a Svelte component as an NPM package and reading this guide. All is good until I read this section:

Well, that is a great idea. Let's test it locally first.
I made a test folder with App.svelte which used my new component. Then, I configured Rollup to build App.svelte. It worked. Great!
Now I wanted to try it in my new project, Backdoor (Postgres Data Querying and Editing Tool that you can embed into your JVM app). I included the dependency by adding the line to package.json as shown below:
{
....
"devDependencies": {
"svelte-virtual-table-by-tanin": "file:../svelte-virtual-table"
}
...
}And it didn't work. The error happened inside Svelte itself and looked totally obscure: Cannot read properties of undefined (reading 'call')

At some point, I also encountered this error: Uncaught TypeError: Cannot read properties of null (reading 'f') because parent_effect is null in the parent_effect.f statement.


This happened within Svelte itself.
After googling it around for hours, nobody encountered the same issue before. There were only a few Svelte issues that had a similar error but not quite match my situation. However, I stumbled upon this comment:

This is an interesting theory. Maybe I had duplicated Svelte runtime in my bundle somehow. So I added the below to my Rollup config:
{
...,
plugins: [
resolve({
...
dedupe: ['svelte']
...
})
]
...
}It worked! But why would I even need this?
The clue was actually in the experiment I did before where the component and the test project were in the same folder vs. in different folders.
When an obscure error like this happens, I often resort to deleting random code to see what impacts the error. So, I deleted the node_modules of the component folder. Then, I ran Rollup. Now it failed when bundling. Rollup complained that the component couldn't find Svelte. But why? It was just a component, not the whole project.
As it turns out, when Rollup builds a component, it will try to find the Svelte runtime by walking up the directory tree in some way (it could be looking for node_modules or package.json; I didn't dive deeper.). If the component and the test project are on 2 different folders, then there are 2 separate node_modules and 2 separate Svelte runtimes (even if they are of identical versions). That was how 2 Svelte runtimes were bundled.
This means we cannot use a local package that links to a folder. npm link also doesn't work because it goes through the same mechanism.
What works is npm pack which generates a tgz file. Then, you can do npm install <tgz_file> to install the package from the compressed file instead.
I've learned something new about how Svelte and a bundler work. Now you've learned it too 😄