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

Package that expose multiple entrypoints with a shared module do not externalize that module #881

Open
paoloricciuti opened this issue Sep 25, 2024 · 3 comments
Labels
browser Not working in Browser

Comments

@paoloricciuti
Copy link

Sorry if i'm not following a template but this is a bit of a special case...the import actually succeed but i think the resulting JS file is unproperly bundled.

So what i'm doing is i'm compiling a svelte component into a JS file. It looks something like this.

import * as $ from "svelte/internal/client";

var root = $.template(`<h1> </h1>`);

export default function App($$anchor, $$props) {
	var h1 = root();
	var text = $.child(h1);

	$.reset(h1);
	$.template_effect(() => $.set_text(text, `Hello ${$$props.greet ?? ""}`));
	$.append($$anchor, h1);
}

then i'm importing this component and hydrate from svelte in my main js file

import Component from "./Component.js";
import { hydrate } from "svelte";

hydrate(Component, {
    target: document.getElementById("app"),
    props: { greet: "world" },
});

i can setup an importmap to map this work like this

<script type="importmap">
    {
        "imports": {
            "svelte": "https://esm.sh/svelte@next",
            "svelte/": "https://esm.sh/svelte@next/"
        }
    }
</script>

however here's where the problem arise. As you can see my main js file it's importing hydrate from svelte (which is the root entry point exposed by svelte) and the Component.js it's importing the client runtime from svelte/internal/client, another entry point exposed by svelte.

Those two modules exposed by svelte both import a third module that expose an export hydrating and some other utilities. However when accessing the module bundled by esm.sh this third shared module is bundled separately in each module so the aforementioned hydrating variable is just a local variable for both modules. This obviously breaks a lot of stuff and the whole thing cease to work.

I can fix this with a slight change to the import map

<script type="importmap">
    {
        "imports": {
            "svelte": "https://esm.sh/svelte@next?no-bundle",
            "svelte/": "https://esm.sh/svelte@next&no-bundle/"
        }
    }
</script>

but this

  1. it's not ideal
  2. ships the library completely unbundled leading to a lot of http requests.

The best option would be for esm.sh to smartly externalize a module if it's shared by multiple exposed entry points of a library. Do you think it could be feasible? Do you see any other solution to this problem?

@paoloricciuti paoloricciuti added the browser Not working in Browser label Sep 25, 2024
@ije
Copy link
Member

ije commented Sep 27, 2024

The best option would be for esm.sh to smartly externalize a module if it's shared by multiple exposed entry points of a library.

i like this idea, we can decide whether a module should be bundled by checking the dependency tree, i will look into it

@Rich-Harris
Copy link

I think it's probably simpler than checking the dependency tree — just pass the entries in package.exports to esbuild as entryPoints and enable splitting: true, and it should do the work for you

@ije
Copy link
Member

ije commented Sep 28, 2024

@Rich-Harris the exports is alreay externalized by default, for example, entries esm.sh/svelte and esm.sh/internal/client share the same module https://esm.sh/stable/[email protected]/[buildtarget]/internal/client.js, and entry esm.sh/svelte imports another module https://esm.sh/stable/[email protected]/es2022/svelte.mjs.

I think the issue @paoloricciuti got is, same modules with side-effect are required by esm.sh/svelte and esm.sh/internal/client are not externalized.

here i found this file(
https://github.com/sveltejs/svelte/blob/35ebbe61adfb09a780806d70f5c0067e6ebd78f7/packages/svelte/src/internal/client/render.js#L171) should be externalized, but it's not declared in the exports field. (it's bundle both in the client.js and svelte.mjs)

Screenshot 2024-09-28 at 13 51 56 Screenshot 2024-09-28 at 13 52 10

@ije ije mentioned this issue Oct 23, 2024
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
browser Not working in Browser
Projects
None yet
Development

No branches or pull requests

3 participants