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

TypeError: store.subscribe is not a function: When config.js is run as an ESM module by using top-level await #1947

Closed
btakita opened this issue Jul 18, 2021 · 5 comments
Labels

Comments

@btakita
Copy link

btakita commented Jul 18, 2021

Describe the bug

When svelte.config.js is forced to be an esm module by using a top-level await and within src/hooks/index.ts:

import svelte/store loads the esm version of svelte/store/index.mjs. ssrTransform in vite overwrites the transpiled writable function to reference subscribe that is imported from internal/index.mjs. This causes the returned Writable store from writable to have the incorrect definition of subscribe.

Due to ssrTransform https://github.com/vitejs/vite/blob/main/packages/vite/src/node/ssr/ssrTransform.ts#L189,
writable in store/index.mjs is transpiled to become:

function writable(value, start = __vite_ssr_import_0__.noop) {
    let stop;
    const subscribers = [];
    function set(new_value) {
        if (__vite_ssr_import_0__.safe_not_equal(value, new_value)) {
            value = new_value;
            if (stop) { // store is ready
                const run_queue = !subscriber_queue.length;
                for (let i = 0; i < subscribers.length; i += 1) {
                    const s = subscribers[i];
                    s[1]();
                    subscriber_queue.push(s, value);
                }
                if (run_queue) {
                    for (let i = 0; i < subscriber_queue.length; i += 2) {
                        subscriber_queue[i][0](subscriber_queue[i + 1]);
                    }
                    subscriber_queue.length = 0;
                }
            }
        }
    }
    function update(fn) {
        set(fn(value));
    }
    function subscribe(run, invalidate = __vite_ssr_import_0__.noop) {
        const subscriber = [run, invalidate];
        subscribers.push(subscriber);
        if (subscribers.length === 1) {
            stop = start(set) || __vite_ssr_import_0__.noop;
        }
        run(value);
        return () => {
            const index = subscribers.indexOf(subscriber);
            if (index !== -1) {
                subscribers.splice(index, 1);
            }
            if (subscribers.length === 0) {
                stop();
                stop = null;
            }
        };
    }
    return { set, update, subscribe: __vite_ssr_import_0__.subscribe };
}

writable(null).subscribe does not operate correctly since subscribe from internal/index.mjs replaces the subscribe defined within the writable function.

Reproduction

https://github.com/btakita/sveltekit-repro-subscribe-issue

svelte.config.js is forced to be an esm module by using a top-level await: https://github.com/btakita/sveltekit-repro-subscribe-issue/blob/main/svelte.config.js#L4

svelte/store writable is transpiled where subscribe is replaced by __vite_ssr_import_0__.subscribe https://github.com/btakita/sveltekit-repro-subscribe-issue/blob/main/src/hooks/index.ts

Logs

No response

System Info

System:
    OS: Linux 5.12 Arch Linux
    CPU: (16) x64 AMD Ryzen 7 5800X 8-Core Processor
    Memory: 33.17 GB / 62.78 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.5.0 - ~/.config/nvm/versions/node/v16.5.0/bin/node
    Yarn: 1.22.10 - /usr/bin/yarn
    npm: 7.19.1 - ~/.config/nvm/versions/node/v16.5.0/bin/npm
  Browsers:
    Brave Browser: 91.1.26.77
    Chromium: 91.0.4472.164
  npmPackages:
    svelte: ^3.35.0 => 3.37.0

Severity

blocking all usage of SvelteKit

Additional Information

No response

@Crisfole
Copy link
Contributor

Crisfole commented Jul 19, 2021

I think (am not sure on this, please don't quote me) that you can actually simply export a promise here, so rather than a top level await wrap it all in a function and export the result of that function or simply use a promise with an async function:

export default new Promise(async resolve => {
  resolve({
     ...
     whatever: await theThing(),
  });
});

@btakita
Copy link
Author

btakita commented Jul 19, 2021

@Crisfole Thank you for the workaround. On my project, I'm getting the same issue whether or not svelte.config.js is a ESM or commonjs. It's just easy to reproduce the behavior using a simple project with svelte.config.js being ESM. I'm also seeing the issue with ssr: false in the kit configuration.

Referencing #1895 vitejs/vite#4230

@benmccann
Copy link
Member

Thanks @btakita for the detailed issue report. I can't say I 100% understand all the details having not had time to dig in, but it sounds like you're describing it as a bug in Vite? If so, it'd be best to file it over in the Vite repo as there will be more people there capable of understanding and fixing the issue. It may help it get looked at by the Vite team if you're able to reproduce it without SvelteKit involved (you can use https://github.com/sveltejs/vite-plugin-svelte/tree/main/packages/e2e-tests/vite-ssr as a starter project). After that, leave a comment on vitejs/vite#4230 pointing to the Vite issue to help make sure we keep track of it and can help get it prioritized in discussions with the Vite team

@benmccann
Copy link
Member

Closing in favor of the Vite issue since I don't think there's anything we can do on the SvelteKit side: vitejs/vite#4306

@AlbertMarashi
Copy link

Getting this issue was well when running master fork of svelte.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants