vite-plugin-svelte icon indicating copy to clipboard operation
vite-plugin-svelte copied to clipboard

get/set/hasContext doesn't work in production code outside a component

Open ciscoheat opened this issue 3 years ago • 5 comments

Describe the bug

I'm trying to use the context functions in library code. They work when using both vite dev and vite preview when linking to the library directly. But when publishing to npm and including the library from there, an exception is thrown (see the logs).

Reproduction

  1. Create a new sveltekit todo app
  2. Add this code to +layout.svelte:
import { Flash } from "sveltekit-flash-message/client"
import { page } from '$app/stores'

const flash = new Flash(page)
const message = flash.message

Explanation

new Flash(page) calls hasContext in its constructor, throwing the error since hasContext cannot find current_component at that point. Code: https://github.com/ciscoheat/sveltekit-flash-message/blob/c5198a35b724d53e0eab780e16d09c7c5c1499fb/src/lib/client.ts#L61-L66

Stackblitz reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-ask2u7?file=src%2Froutes%2F%2Blayout.svelte&terminal=dev

Logs

Error: Function called outside component initialization
    at get_current_component (file:///E:/Projects/TEST/svelte-next/node_modules/.pnpm/[email protected]/node_modules/svelte/internal/index.mjs:953:15)
    at hasContext (file:///E:/Projects/TEST/svelte-next/node_modules/.pnpm/[email protected]/node_modules/svelte/internal/index.mjs:995:12)
    at debugflash (file:///E:/Projects/TEST/svelte-next/node_modules/.pnpm/[email protected]/node_modules/sveltekit-flash-message/client.js:52:7)
    at file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/entries/pages/_layout.svelte.js:16:3
    at Object.$$render (file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/chunks/index.js:89:18)
    at file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/index.js:36:97
    at $$render (file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/chunks/index.js:89:18)
    at Object.render (file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/chunks/index.js:97:20)
    at render_response (file:///E:/Projects/TEST/svelte-next/.svelte-kit/output/server/index.js:938:29)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

System Info

System:
    OS: Windows 10 10.0.19043
    CPU: (16) x64 Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
    Memory: 43.25 GB / 63.93 GB
  Binaries:
    Node: 16.16.0 - C:\Program Files\nodejs\node.EXE
    npm: 8.11.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (104.0.1293.70)
    Internet Explorer: 11.0.19041.1566
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.71
    @sveltejs/kit: next => 1.0.0-next.460
    svelte: ^3.49.0 => 3.49.0
    vite: ^3.1.0-beta.1 => 3.1.0-beta.1

Severity

blocking all usage of SvelteKit

Additional Information

No response

ciscoheat avatar Sep 01 '22 07:09 ciscoheat

This sounds like Vite does somehow create a separate Svelte runtime instance for the library. Your package is using @sveltejs/package which rules one source of errors out, which is good. I wonder if it's because your package doesn't contain Svelte components, yet it uses functions from it, so vite-plugin-svelte doesn't detect it's related to Svelte and doesn't handle it specifically or something. cc @dominikg @bluwy

dummdidumm avatar Sep 01 '22 08:09 dummdidumm

If you need more information, or can point me in some direction for testing this in more depth, let me know!

ciscoheat avatar Sep 01 '22 08:09 ciscoheat

I thought this was already fixed via https://github.com/sveltejs/vite-plugin-svelte/issues/360. A workaround for now is to add this in vite.config.js:

	ssr: {
		noExternal: ['sveltekit-flash-message']
	}

bluwy avatar Sep 01 '22 08:09 bluwy

Tested right away, confirmed that it works with that addition! Can this be fixed (added automatically/programatically?), so I don't have to ask library users to add this to their config, thereby increasing the friction?

ciscoheat avatar Sep 01 '22 08:09 ciscoheat

It should be added automatically but it's not, which sounds like a bug. I'll transfer this over to vite-plugin-svelte to track there onwards.

bluwy avatar Sep 04 '22 08:09 bluwy

When I run your example I don't see the log message you provided. Can you provide an actual reproduction of this issue?

benmccann avatar Oct 05 '22 17:10 benmccann

Strange, I got it immediately using the latest sveltekit, both locally and on stackblitz. Here it is on stackblitz again: https://stackblitz.com/edit/sveltejs-kit-template-default-qwph8i?file=vite.config.js,src%2Froutes%2FHeader.svelte&terminal=dev

ciscoheat avatar Oct 06 '22 09:10 ciscoheat

Having the same issue and the only way to resolve it is to add the package in noExternal. I remember external libraries being able to use contexts in July/August, not sure which version though.

pilcrowonpaper avatar Oct 28 '22 14:10 pilcrowonpaper

Are you using the latest SvelteKit? What happens if you set vitePlugin.prebundleSvelteLibraries to false in svelte.config.js? I have a hunch this is related to prebundleSvelteLibraries being true by default now (PR: https://github.com/sveltejs/kit/pull/7388).

dummdidumm avatar Oct 28 '22 15:10 dummdidumm

Is this correct?

const config = {
	kit: {
		adapter: adapter(),
		
	},
	vitePlugin: {
		prebundleSvelteLibraries: false
	}
};

It's still causing errors. Something interesting is that my package works inside a monorepo (imported via "lucia-auth": "workspace:*") when using pnpm, but breaks when using a published version using npm.

pilcrowonpaper avatar Oct 28 '22 23:10 pilcrowonpaper

unfortunately prebundleSvelteLibraries is forced true in sveltekit right now as it is passed as an inline option. these have precedence over options specified in the config file.

https://github.com/sveltejs/kit/blob/edd815ed7bba7ab88461f9291f924c05a01d1328/packages/kit/src/exports/vite/index.js#L64 introduced here: https://github.com/sveltejs/kit/commit/e25074cfedd4147cf3091442cd7687828c6282a9#diff-beef34c36ed87d7835d0166655010910fba9949a6ef95042cb468d7d73423816R64

The only workaround for that i see is using something like pnpm patch to change the value provided inline in svelte-kit.

cc @benmccann

dominikg avatar Oct 29 '22 10:10 dominikg

@pilcrowOnPaper can you provide a repository with a reproduction?.

benmccann avatar Oct 29 '22 12:10 benmccann

vite-plugin-svelte 1.2.0 improved how prebundleSvelteLibraries works and i cannot reproduce the stacktrace from the original post with that. Unfortunately i'm not sure what is supposed to happen instead of that error so i would appreciate if @ciscoheat could confirm it works now.

And @pilcrowOnPaper if you still find issues with 1.2.0 and prebundleSvelteLibraries, a reproduction would be greatly appreciated. thanks (:

dominikg avatar Nov 18 '22 08:11 dominikg

@dominikg I just tested it with the latest sveltekit, but still the same "Function called outside component initialization" problem. It works immediately when I add this to vite.config.js:

ssr: {
  noExternal: ['sveltekit-flash-message']
}

ciscoheat avatar Nov 28 '22 10:11 ciscoheat

@ciscoheat looking at https://publint.bjornlu.com/[email protected] , there is no peerDependency on svelte. This completely relies on the users project setup having deduplication for svelte and pulling it in anyways, potentially causing problems after svelte-4 release if the apis differ there. You should declare the peerDependency and vite-plugin-svelte is going to add the noExternal entry automatically.

This peerDependency declaration is not needed for ui libraries the only distribute .svelte source code, but it is needed if you make use of svelte apis in the library itself.

dominikg avatar Nov 28 '22 10:11 dominikg

If that still doesn't help, please create an updated reproduction with step-by-step instructions on how to produce the error message (preferably from scratch with the sveltekit skeleton or vite+svelte template, not the sveltekit demo app)

dominikg avatar Nov 28 '22 10:11 dominikg

update, seems you're using sveltekit directly too, so that also needs to be a peerDependency https://github.com/ciscoheat/sveltekit-flash-message/blob/master/src/lib/server.ts#L2

dominikg avatar Nov 28 '22 10:11 dominikg

Thank you, the peer dependency fixes solved the issue. It's quite intricate, so I appreciate your help!

ciscoheat avatar Nov 28 '22 12:11 ciscoheat

@dominikg Just updated my library and can confirm the issue has been resolved by adding svelte to peerDependencies. Thanks!

pilcrowonpaper avatar Dec 03 '22 11:12 pilcrowonpaper