Skip to content
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

Svelte component bundled with outros throws at runtime #3964

Closed
caqu opened this issue Nov 20, 2019 · 13 comments
Closed

Svelte component bundled with outros throws at runtime #3964

caqu opened this issue Nov 20, 2019 · 13 comments

Comments

@caqu
Copy link

caqu commented Nov 20, 2019

Describe the bug
When bundling a Svelte component into a module, then loading it dynamically, the outros function is missing and this causes a runtime error when the component is scheduled to unload.

To Reproduce
I created a live demo here:
https://practical-bartik-9883e1.netlify.com

The source is here:
https://github.com/caqu/import-svelte/tree/master/src
https://github.com/caqu/import-svelte/blob/master/rollup.config.js

The issue I see is rooted here on the generated code:
https://practical-bartik-9883e1.netlify.com/build/child_with_fade.js

...
let outros;
function transition_in(block, local) {
    if (block && block.i) {
        outroing.delete(block);
        block.i(local);
    }
}
const null_transition = { duration: 0 };
function create_out_transition(node, fn, params) {
    let config = fn(node, params);
    let running = true;
    let animation_name;
    const group = outros;                       // <------ Outros is undefined
    group.r += 1;

Logs

index.mjs:762 Uncaught (in promise) TypeError: Cannot read property 'r' of undefined
    at create_out_transition (index.mjs:762)
    at Object.o (index.mjs:51)
    at G (index.mjs:691)
    at Object.p (App.svelte:47)
    at q (index.mjs:638)
    at P (index.mjs:612)
create_out_transition @ index.mjs:762
o @ index.mjs:51
G @ index.mjs:691
p @ App.svelte:47
q @ index.mjs:638
P @ index.mjs:612
Promise.then (async)
V @ index.mjs:591
(anonymous) @ index.mjs:1337
remove_child_with_fade @ App.svelte:18

Expected behavior
I'm relatively new to Svelte and Rollup, so it's possible there's a config error in my Rollup file.

Severity
This seems to be an issue that's impacting many developers using dynamic imports and routing. I believe it may also be the root cause of:
#3448
#3165

Additional Context
The issue seems to appear when adding a < slot / > to the child component.

@caqu caqu changed the title Svelte component bundled without outros throws at runtime Svelte component bundled with outros throws at runtime Nov 20, 2019
@arggh
Copy link
Contributor

arggh commented Feb 3, 2020

I just opened an old project, updated it to 3.18.1 (latest) and bumped into this.

A buggy version of npm is doing funky things and installing duplicate versions of Svelte all over the place. It had nothing to do with the Svelte version.

Stacktrace
Uncaught (in promise) TypeError: Cannot read property 'c' of undefined
    at transition_out (modules.js?hash=574e2833e0bc262823d4387523c68d3252981b3b:30598)
    at Object.outro [as o] (modules.js?hash=574e2833e0bc262823d4387523c68d3252981b3b:7980)
    at transition_out (index.mjs:717)
    at Object.outro [as o] (PageCreateProfile.svelte:77)
    at transition_out (index.mjs:717)
    at Object.outro [as o] (Nav.svelte:10)
    at transition_out (index.mjs:717)
    at Object.outro [as o] (PageCreateProfile.svelte:77)
    at transition_out (index.mjs:717)
    at Object.update [as p] (PageSignup.svelte:9)
Breaking code
function transition_out(block, local, detach, callback) {
    if (block && block.o) {
        if (outroing.has(block))
            return;
        outroing.add(block);
        outros.c.push(() => {  // <---- outros is undefined
            outroing.delete(block);
            if (callback) {
                if (detach)
                    block.d(1);
                callback();
            }
        });
        block.o(local);
    }
}

In my case, the error is thrown if the Svelte component imported from a package uses another components from the same package internally.

Well, it seems this pattern of including another component within the same package does bring out the bug, but it was still only caused by buggy npm installing duplicate versions of Svelte all over the place.

Nuking node_modules, downgrading npm and re-installing helped.

@crisward
Copy link

crisward commented Mar 5, 2020

Just hit this problem after moving our shared components out into its own modules. During development we're using npm link but webpack is getting two copies of svelte.

Found this writeup

https://medium.com/@penx/managing-dependencies-in-a-node-package-so-that-they-are-compatible-with-npm-link-61befa5aaca7

The TLDR; is, if you're using webpack and npm linking your components in, get them to resolve to the same version of svelte by adding this to your webpack config. This worked for me.

const path = require("path");

{
// usual webpack config +
resolve: { 
  alias:{
    "svelte":path.resolve(__dirname, "node_modules/svelte"),
    }
  }
}

In production we would just npm install the modules so they resolve svelte from the host project. The above change shouldn't break anything in the host project as that's where it'd look for svelte anyway.

@daniloster
Copy link

I came across this issue, and I have been looking after it. I don't get the reason for the error yet.

I have checked all the possibilities pointed here and none of them helped.

  • resolve alias
  • nuking node_modules
  • only have 1 svelte version installed

I have wrote a lib @daniloster/svelte-i18n which is getting this error when is being consumed inside an if block.

{#if isOpen}
  <CustomComponent />
{/if}

CustomComponent.svelte

<div>
  <Literal {namespace} path="create"/>
</div>

When isOpen get value changed to false, the "outros"is undefined. No transitions (svelte/transition) have been added.

May I have some help with it, please?

@daniloster
Copy link

I have checked the thread comment #3448 (comment)

And I have changed the library to publish only babel transpilation + svelte file. This way, compilation will happen in the end-app.

Thanks everyone.

@lagden
Copy link

lagden commented May 12, 2020

I've made a tiny component to use into project. (https://github.com/lagden/svelte-btn)
I found the same problems above, but I realized some interesting behavior.

In my case, the error only happens if I use a svelte component as child.
https://svelte.dev/repl/be4907a42a3f491b92e577c42fb7fb3a?version=3.22.2

REPL fragment code BtnDyn.svelte

<script>
  import Btn from '@tadashi/svelte-btn/dist/index.mjs'
  //... code stuff
</script>

<Btn class="{cssTheme} {className}" {...filtered} on:click>
  {#if icoName}
    <Icon name="ico_{icoName}" class="{_icon} {value ? _icon_margin : ''}" />
  {/if}
</Btn>

If you replace by pure HTML, the component will work!

<Btn class="{cssTheme} {className}" {...filtered} on:click>
  {#if icoName}
    <svg class="{_icon} {value ? _icon_margin : ''}">
      <use xlink:href="#residencial_ico_{icoName}" />
    </svg>
  {/if}
</Btn>

I think it's a bug, because the component and your children are render.
This should be analyzed. IMO.


Obs.:

If use import Btn from '@tadashi/svelte-btn will work because the main file in package.json is src/index.svelte

https://github.com/lagden/svelte-btn/blob/master/package.json#L24-L25

@Egnus
Copy link

Egnus commented May 16, 2020

I can also confirm that this issues happens, in my case is by using svelte-routing with if conditions.
with Svelte 3.20.1 everything works but it fails with the changes added in Svelte 3.21.0.

Possible duplicated from #3448

@lagden
Copy link

lagden commented May 17, 2020

@Egnus

The svelte-routing works fine and it's not a problem with if-statements!
This problem occurs when you use a svelte component (compiled) into slot.

Make a simple test, replace the content of if-statements by simple one:

{#if}
  <p>test</p>
{/if}

@Conduitry
Copy link
Member

Is there anything going on here that's different from the many other issues that have been opened about problems that happen when there are two copies of the Svelte internals bundled into an app? This sounds to me like just another occurrence of that. You need to make sure the published component has a svelte field in it, and you need to make sure that the bundler is deduping instances of the svelte package so that there's only one copy of svelte/internals.

@arggh
Copy link
Contributor

arggh commented Jun 8, 2020

Just a late night idea: would be sweet, if Svelte had (at least in dev mode) a mechanism to detect multiple instances of Svelte's internals.

That would:

a) Reduce the amount of weird and non-existent bugs due to having two runtimes present
b) Prevent apps from breaking when accidentally shipping two runtimes for whatever reason

@Koleok
Copy link

Koleok commented Feb 10, 2021

As usual in these types of cases, forcing the version via resolutions in package.json to the version I currently had installed worked for me

  "resolutions": {
    "svelte": "^3.32.1"
  }

@stale
Copy link

stale bot commented Jun 26, 2021

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.

@stale stale bot added the stale-bot label Jun 26, 2021
@stale stale bot removed the stale-bot label Jun 26, 2021
@stale stale bot removed the stale-bot label Jun 27, 2021
@stale
Copy link

stale bot commented Dec 29, 2021

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.

@Rich-Harris
Copy link
Member

Closing in favour of #2864

@Rich-Harris Rich-Harris closed this as not planned Won't fix, can't repro, duplicate, stale Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests