Svelte: bind:this does not work in code outside of the app itself

Created on 3 Jun 2019  路  10Comments  路  Source: sveltejs/svelte

bind:this only seems to work when the code is located in the same module as the app code.

This is problematic for library code such as a UI component library.

To demonstrate the problem, I've created a minimal Button component inside a (mini) monorepo.

When using the exact same Button code, the binding only works for the local Svelte module.

These do not work (as in: they do render but without the binding):

import { Button } from "lib-with-bind-this"
import ButtonFromPath from "../../lib-with-bind-this/src/Button.svelte"

This does work:

import LocalButton from "./LocalButton.svelte"

I've created a small demo project that shows the behavior:
https://github.com/ArthurClemens/test-bind-this (instructions provided).

Most helpful comment

Update

My team has used webpack's resolve.alias field to solve the problem.

Summarizing my environment(updated) details and the steps that helped us:

Environment

"svelte": "3.6.3",
"svelte-loader": "2.13.3"
"webpack": "4.35.2"
"webpack-cli": "3.3.5"

Steps

  1. In my component's _package.json_

    • I have added svelte:property (Refer svelte-loader's readme)

    • I have also added svelte under peerDependencies

  1. In my app's _webpack.config.js_
resolve: {
    mainFields: ['svelte'],
    alias: {
        svelte: path.resolve('node_modules','svelte')
    },
    extensions: ['.mjs', '.js', '.svelte']
},

From what I understood, rollup has a _rollup-plugin-node-resolve_ plugin which has a _dedupe_ config and achieves something similar.
This article helped us understand and come up with the above solution

I am also open to any suggestions\feedback OR a more appropriate way of handling this issue.

All 10 comments

This problem is related to the discussion at #2896 (since they closed that one, we can keep track of it here): Svelte components can't properly consume other pre-compiled Svelte components because you end up with multiple, distinct svelte/internal modules that do not share information.

I believe we need to figure out an internal api for Svelte to connect third-party components' internals at instantiation.

In the meanwhile, if these components can share the same build process, consider using the package.json's svelte: property to tell bundlers where to get the components' source from and make Svelte a peerDependency instead.

How do I use package.json's svelte: property?

Just point it to your package's main source file (be that a .svelte file or a .js exporting multiple components). See https://github.com/rollup/rollup-plugin-svelte/#pkgsvelte.

Including svelte in package.json doesn't help my case: the binding still doesn't work.

You also need to make svelte a peerDependency, which means removing it from the component's (subpackage) node_modules as well.

It seems to be the same issue that I have on #2620, is it?

Hi All,
I am using webpack(4.34.0) to bundle svelte(3.5.1) components.
and I am running into the same issue as well.

As suggested by @mrkishi, my app & components could potentially share the same build process.

So, in my component's package.json

  1. I have added svelte: property
  2. I have also added svelte under peerDependencies

After this when I build my app I run into following error -
... Module not found: Error: Can't resolve 'svelte' in '...\ ... Module not found: Error: Can't resolve 'svelte/internal' in '...\

Could any one help me with steps\pointers to fix this.


Also looking at @Conduitry's reply here , does it mean that the issue will be solved only if we use rollup and rollup-plugin-svelte for bundling ?

Update

My team has used webpack's resolve.alias field to solve the problem.

Summarizing my environment(updated) details and the steps that helped us:

Environment

"svelte": "3.6.3",
"svelte-loader": "2.13.3"
"webpack": "4.35.2"
"webpack-cli": "3.3.5"

Steps

  1. In my component's _package.json_

    • I have added svelte:property (Refer svelte-loader's readme)

    • I have also added svelte under peerDependencies

  1. In my app's _webpack.config.js_
resolve: {
    mainFields: ['svelte'],
    alias: {
        svelte: path.resolve('node_modules','svelte')
    },
    extensions: ['.mjs', '.js', '.svelte']
},

From what I understood, rollup has a _rollup-plugin-node-resolve_ plugin which has a _dedupe_ config and achieves something similar.
This article helped us understand and come up with the above solution

I am also open to any suggestions\feedback OR a more appropriate way of handling this issue.

@prashantsail Thank you very much for that! The webpack templates now have resolve.alias in their config and the Rollup templates are using the dedupe option to rollup-plugin-node-resolve.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

noypiscripter picture noypiscripter  路  3Comments

Rich-Harris picture Rich-Harris  路  3Comments

davidcallanan picture davidcallanan  路  3Comments

juniorsd picture juniorsd  路  3Comments

ricardobeat picture ricardobeat  路  3Comments