Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

FullCalendar is broken with SvelteKit #804

Closed
TheophileMot opened this issue Dec 19, 2021 · 50 comments · Fixed by #934
Closed

FullCalendar is broken with SvelteKit #804

TheophileMot opened this issue Dec 19, 2021 · 50 comments · Fixed by #934

Comments

@TheophileMot
Copy link

TheophileMot commented Dec 19, 2021

@YogliB

FullCalendar doesn't work in SvelteKit projects; it gives the following error in the console:

svelte-fullcalendar doesn't appear to be written in CJS, but also doesn't appear to be a valid ES module (i.e. it doesn't have "type": "module" or an .mjs extension for the entry point). Please contact the package author to fix.

10:15:31 p.m. [vite] Error when evaluating SSR module /node_modules/preact/compat/dist/compat.module.js?v=39414b8c:
ReferenceError: __vite_ssr_import_1__ is not defined
    at eval (/node_modules/preact/compat/dist/compat.module.js?v=39414b8c:11:712)
    at async instantiateModule (.../svelte-fullcalendar/examples/kit/node_modules/vite/dist/node/chunks/dep-5496817b.js:67449:9)

To reproduce, try running the demo in /examples/kit. I tried changing the SSR settings, both globally (in svelte.config.js) as well as locally (in the index.svelte file that loads the calendar) but didn't have any luck.

@benmccann
Copy link
Contributor

benmccann commented Dec 29, 2021

PR to fix the warning: #806

The error is a different issue

@TheophileMot
Copy link
Author

TheophileMot commented Dec 29, 2021

@benmccann The error in question is __vite_ssr_import_1__ is not defined. I believe the module warning is unrelated (those lines do get rid of that warning message, but don't fix the problem).

From what I understand, the issue is that the underlying fullcalendar package refers to document and window, so for some technical reason, the svelte-fullcalendar import needs to be inside onMount. In other words, instead of

import FullCalendar from 'svelte-fullcalendar';

it should be

let FullCalendar = null;

  onMount(async () => {
    FullCalendar = (await import('svelte-fullcalendar')).default;
    ...
  }  

@YogliB
Copy link
Owner

YogliB commented Jan 5, 2022

I'll look at it later today, thanks for reporting!

@Snukii
Copy link

Snukii commented Jan 6, 2022

I'm also getting hit with __vite_ssr_import_1__ is not defined in sveltekit

TheophileMot's fix doesn't seem to work either, that gives me: Uncaught (in promise) TypeError: ctx[0] is not a constructor

@TheophileMot
Copy link
Author

TheophileMot commented Jan 12, 2022

@Snukii My implementation is working well now. What if you try this?

<script>
  // ...

  let FullCalendar;
  onMount(async () => {
    FullCalendar = (await import('svelte-fullcalendar')).default;
    const common = (await import('@fullcalendar/common')).default;
    options = {
      ...options,
      plugins: [
        (await import('@fullcalendar/daygrid')).default,
        (await import('@fullcalendar/interaction')).default,
      ],
    };
  });
</script>

{#if FullCalendar}
  <FullCalendar {options} />
{/if}

@TheophileMot
Copy link
Author

TheophileMot commented Jan 13, 2022

My implementation is working well now.

Hmm... it's mostly working, anyway. I thought everything was fine, but now I sometimes get __vite_ssr_import_1__ is not defined again, even though I haven't changed anything in my setup.

Edit: I think the error message just occurs when it's recompiling (e.g., when switching branches in Git), so everything's working fine at the moment.

@goynang
Copy link

goynang commented Jan 18, 2022

I've found that...

import '@fullcalendar/core/vdom'

...helped me as per fullcalendar/fullcalendar-vue#152 and Vue example on https://fullcalendar.io/docs/vue

@YogliB
Copy link
Owner

YogliB commented Jan 19, 2022

@goynang

didn't notice in the docs, thanks!

anyway, we already do it inside the component code, so i'm not sure if this would make a difference.

@TheophileMot
Copy link
Author

@goynang Thank you! It wasn't working for me in production, but that line fixed the problem. (So @YogliB, yes, it does make a difference.)

@YogliB
Copy link
Owner

YogliB commented Feb 8, 2022

@TheophileMot
i'll try to look at it soon, it might mean we can stop loading vdom inside the component.

@YogliB YogliB closed this as completed Feb 17, 2022
@vhscom
Copy link
Contributor

vhscom commented Mar 20, 2022

Was seeing same error as OP on SvelteKit beta 301 and scratching my head as to why the kit example in this repo was working but not the NPM module. Then I saw there's a tagged release for svelte-fullcalendar called experimental currently on version 2.0.0-experimental.1. Once I pulled that into my project from NPM and installed the missing peer dependencies indicated (e.g. pnpm add -D @fullcalendar/core @fullcalendar/common) I was able to move past this error, which in my case using PNPM output like this:

1:20:35 PM [vite] Error when evaluating SSR module /node_modules/.pnpm/preact@10.6.6/node_modules/preact/compat/dist/compat.module.js?v=94a4ec96:
ReferenceError: __vite_ssr_import_1__ is not defined

Note no changes were required to vite config in svelte.config.js, and no vdom import hacks used.

@YogliB
Copy link
Owner

YogliB commented Mar 20, 2022

@vhscom

very weird, i tried using the experimental package in a blank project but I didn't get it to work 🤦

@vhscom
Copy link
Contributor

vhscom commented Mar 20, 2022

Adding svelte-fullcalendar was the second step I took after scaffolding a new project so there's very little at play in the repo I'm working on (read: no magic or hacks or potential for corner cases), and the experimental NPM module is working for me with PNPM.

If I have a chance later I'll circle back with an example but as it stands the experimental tag fixed the issue and I'm able to reproduce the kit example entirely with drag-and-drop support without any errors and without doing any funny assignments preceding the dynamic imports in onMount.

@YogliB
Copy link
Owner

YogliB commented Mar 20, 2022

@vhscom
I'll check it again, and if it works for me I'll release a new major version.
thanks for letting me know!

@vhscom
Copy link
Contributor

vhscom commented Mar 20, 2022

I'd like to point out I'm also able to get the calendar to display without using dynamic imports (in other words, no need to use onMount) by deduping @fullcalendar/common once added to my project. Got the idea here after seeing fullcalendar/fullcalendar#6370 and here's what it looks like in the Kit config:

kit: {
  adapter: adapter(),
  vite: {
    resolve: {
      dedupe: ['@fullcalendar/common']
    },
    optimizeDeps: {
      include: ['@fullcalendar/common']
    }
  }
}

I believe @TheophileMot may be interested in that. ☝️

And, perhaps @Masatoshi could help get you across the finish line for a v2 release as they seem to have some experience handling bundler peculiarities. Finally, I think working but not perfect v2-beta (also mentioned in the readme) is better than a not working NPM module out of the box experience, especially since SvelteKit is gaining a lot of momentum. Just my two cents. Regardless, you're doing a great job. Thanks for putting this together.

@YogliB YogliB reopened this Mar 20, 2022
@YogliB
Copy link
Owner

YogliB commented Mar 31, 2022

Hey, y'all 👋
I just released a new beta version, and it would be great if you would read the updated README and try it out.

Great thanks to @vhscom for finding a way to get FullCalendar work in SvelteKit (the example also got updated) 🎉

@vhscom
Copy link
Contributor

vhscom commented Apr 1, 2022

Tested 2.0.0-beta.0 with success. Regarding the instructions I wanted to mention you could combine the following:

import type { CalendarOptions } from 'svelte-fullcalendar';
import FullCalendar from 'svelte-fullcalendar';

Can be reduced to:

import FullCalendar, { type CalendarOptions } from 'svelte-fullcalendar';

If you wanted. And it would be nice to see spaces instead of tabs the the README for readability purposes as browsers default to 8 spaces per tab when the tab-size css property isn't set. Neither are very urgent of course. 🙂

@YogliB
Copy link
Owner

YogliB commented Apr 1, 2022

@vhscom
Very nice!
Want to do a PR to update the READMEs & the example?

And I think I'll wait a month or so before closing this issue and releasing a stable version.

@WeAreELIC
Copy link

WeAreELIC commented May 24, 2022

Hey all, what's the status of this? I just tried using this package with a fresh install of SvelteKit (v1.0.0-next.343) and I'm getting the following error: Please import the top-level fullcalendar lib before attempting to import a plugin.

It was, seemingly, working once, and then, after installing another package, it broke again. I uninstalled that package and I'm still getting this error.

@YogliB
Copy link
Owner

YogliB commented May 24, 2022

Hey @WeAreELIC 👋 thanks for using the package!
did you follow the README?

@WeAreELIC
Copy link

@YogliB — Yes, I followed the README on the main branch. I am not using TypeScript in SvelteKit, so not sure if that's an issue. Thanks!

@YogliB
Copy link
Owner

YogliB commented May 25, 2022

@WeAreELIC
it seems like it's broken with the latest version of SvelteKit, I'll take a look...

@vhscom
Copy link
Contributor

vhscom commented May 26, 2022

If it helps Yogev, I've found the following workflow useful for managing kit updates:

  • Pick a minimum supported kit version and document it in the readme with a badge like Minimum SvelteKit version.
  • The badge links to that version in the kit changelog, which I scan for [breaking] changes regularly.
  • Upgrade to the latest kit version at least once a week to keep up-to-date.
  • Leverage browser tests to catch possible regressions.

Considering you have Cypress installed perhaps it can be configured to kick off a test once run a day to check for errors with the latest SK. That ought to signal the need for an example update for those looking into the lib.

@torphix
Copy link

torphix commented Jun 29, 2022

Hi @YogliB,
Thanks for the lib.
I managed to get it working with sveltekit using the following code:

	let FullCalendar: any;

	let options: any;
	onMount(async () => {
		FullCalendar = (await import('svelte-fullcalendar')).default;
		const common = (await import('@fullcalendar/common')).default;
		options = {
			...options,
			plugins: [
				(await import('@fullcalendar/daygrid')).default,
				(await import('@fullcalendar/interaction')).default
			]
		};
	});

However it is non reactive.. therefore I instantiate the FullCalendar component using <svelte:component this={FullCalendar} {...options}> however this doesn't work.
I have tried to follow the exact instructions as specified in the README to no avail.
Also when just using the abov code snippet coupled with <FullCalendar {options}> the calendar renders however I am unable to also import other packages for interactivity etc.
Any help would be greatly appreciated..
Thank you!

@ondrejrohon
Copy link

Any update on this? Thanks

@YogliB
Copy link
Owner

YogliB commented Jul 3, 2022

@ondrejrohon
Unfortunately no...

@YogliB
Copy link
Owner

YogliB commented Jul 22, 2022

@torphix @ondrejrohon

both example & README have been updated, can you give it another try?

@WeAreELIC
Copy link

Awesome, it seems to be working great now, thanks!

@YogliB
Copy link
Owner

YogliB commented Jul 25, 2022

@WeAreELIC
not me, probably a SvelteKit update...

@Wregaan
Copy link

Wregaan commented Oct 13, 2022

Hey @torphix, @YogliB

I had the exact same issue with reactivity just like trophix. However, it seems like I managed to do some workaround the issue.

TL;DR

  1. Get the API that lies under the wrapper like this:

<FullCalendar {options} bind:this={calendarRef} />

  1. In "onMount", create a timeout (play with the delay):

setTimeout(() => rerenderCalendar(), 500);

  1. Create the function:
    function rerenderCalendar() { const api = calendarRef?.getAPI(); if (api && typeof api.render === 'function') { api.destroy(); api.render(); } }

Long story

Due to mounting sequence, the "rerenderCalendar()" cannot be called inside "onMount", because calendarRef will still be null. By creating the timer, we can avoid calendarRef null issue, and even if the timer expires after the page has been resized, the the component will adapt to the new size.

And the true magic is that after doing this once, the entire component becomes fully reactive. I honestly do not know why.

My config is the following:

SvelteKit: 1.0.0-next.515

vite.config.ts:
const config: UserConfig = { plugins: [sveltekit()], resolve: { dedupe: ['@fullcalendar/common'] }, optimizeDeps: { include: ['@fullcalendar/common'] } };

FullCalendar import:
import FullCalendar, { type CalendarOptions } from 'svelte-fullcalendar'; import daygridPlugin from '@fullcalendar/daygrid';

FullCalendar options:

let options: CalendarOptions = { initialView: 'dayGridMonth', events: [], dayMaxEvents: 2, handleWindowResize: true, weekends: false, windowResizeDelay: 5, eventClick: eventClick, headerToolbar: { left: 'prev', center: 'title', right: 'today next' } };

One last thing to note is that I did not build the project, all my experiences coming form dev.

Cheers

@benlau6
Copy link

benlau6 commented Nov 29, 2022

Hey all, what's the status of this? I just tried using this package with a fresh install of SvelteKit (v1.0.0-next.343) and I'm getting the following error: Please import the top-level fullcalendar lib before attempting to import a plugin.

It was, seemingly, working once, and then, after installing another package, it broke again. I uninstalled that package and I'm still getting this error.

It happens again at @sveltejs/kit@1.0.0-next.567. According to problems with Vite, ordering of import statements #152 and Cannot use import statement outside a module #4504, it can be fixed by

  1. Add following code to vite.config.js to fix Cannot use import statement outside a module in advance
// vite.config.js
const config = {
  ...
  ssr: {
    noExternal: ['@fullcalendar/core']
  }
};
  1. Import @fullcalendar/core/vdom right before importing FullCalendar to fix Please import the top-level fullcalendar lib before attempting to import a plugin.
// Component.svelte
<script>
import '@fullcalendar/core/vdom';
import FullCalendar, { type CalendarOptions } from 'svelte-fullcalendar';
...
</script>

@YogliB
Copy link
Owner

YogliB commented Nov 29, 2022

hey @benlau6 👋
can you make a PR to update the example?

@benlau6
Copy link

benlau6 commented Nov 29, 2022

hey @benlau6 👋 can you make a PR to update the example?

Sure, will make it later today

@benlau6 benlau6 mentioned this issue Nov 29, 2022
@benmccann
Copy link
Contributor

benmccann commented Nov 29, 2022

noExternal: ['@fullcalendar/core']

You should not have to do this. It's a sign that something else is wrong. In this case, it looks like the packaging could be updated a bit: fullcalendar/fullcalendar#7038

@benlau6
Copy link

benlau6 commented Nov 29, 2022

noExternal: ['@fullcalendar/core']

You should not have to do this. It's a sign that something else is wrong. In this case, it looks like the packaging could be updated a bit. See https://publint.bjornlu.com/@fullcalendar/core

How about keeping vite.config.js unchanged, but import vdom.cjs instead?

By just adding the following line, it fixes the issue. But it will lead to FullCalendar VDOM already loaded warning in the browser console, and I have no idea how to fix it.

// Component.svelte
<script>
import '@fullcalendar/core/vdom.cjs';
import FullCalendar, { type CalendarOptions } from 'svelte-fullcalendar';
...
</script>

FullCalendar VDOM already loaded might due to the following import sequence from

// FullCalendar.svelte from svelte-fullcalendar
import { Calendar } from '@fullcalendar/core
...
// Calendar.svelte from @fullcalendar/core
import './vdom'
...

By the way, according to jochemvogel at #928 (comment), it works by just adding the vdom.cjs import line inside the package as follows.

// FullCalendar.svelte from svelte-fullcalendar
import '@fullcalendar/core/vdom.cjs';
import { Calendar } from '@fullcalendar/core
...

But I'm not sure what is await import('@fullcalendar/core/vdom.js'); for and if I can delete the whole line. I tried to delete it in the given example, which is fine.

@benmccann
Copy link
Contributor

That's a terrible solution, honestly. CJS should never be used in the browser

I'm not sure what is await import('@fullcalendar/core/vdom.js'); for and if I can delete the whole line

That imports the ESM version, which is a much better solution if you must manually specify a version like this.

But really the fullcalendar package should just define vdom in exports: https://nodejs.org/api/packages.html#subpath-exports

@devShamim
Copy link

devShamim commented Dec 13, 2022

Here how I solved this issue. Import @fullcalendar/core/vdom just before you import svelte-fullcalendar and other fullcalendar plugins. Like this:
import '@fullcalendar/core/vdom';
import FullCalendar from 'svelte-fullcalendar';
import daygridPlugin from '@fullcalendar/daygrid';

I am using the beta version of svelte-fullcalendar which is 2.0.0-beta.0 along with vite-4.0.1

@Snukii
Copy link

Snukii commented Feb 2, 2023

I'm running into Missing "./vdom" specifier in "@fullcalendar/core" package and non of the fixes here seem to work

@Snukii
Copy link

Snukii commented Feb 2, 2023

I'm running into Missing "./vdom" specifier in "@fullcalendar/core" package and non of the fixes here seem to work

Downgrading all the @fullcalendar/ packages to 5.x.x seems to have fixed this issue for me

@frederikhors
Copy link

frederikhors commented Feb 11, 2023

If I use "svelte-fullcalendar": "2.0.0-beta.0" I get an npm install error about dependency conflict with @fullcalendar/core@5 version.

@kevinJread
Copy link

Got it working thanks to this thread. Thank you !!
Here's my config, package and code:

<script lang="ts"> import '@fullcalendar/core/vdom'; import FullCalendar, { type CalendarOptions } from 'svelte-fullcalendar'; import daygridPlugin from '@fullcalendar/daygrid'; let options: CalendarOptions = { initialView: 'dayGridMonth', plugins: [daygridPlugin] }; </script>

<FullCalendar {options} />

-- Package.json
"devDependencies": {
"@fullcalendar/common": "^5.11.4",
"@fullcalendar/core": "^5.0.0",
"@fullcalendar/daygrid": "^5.0.0",

-- vite.config

const config: UserConfig = {
plugins: [sveltekit()],
resolve: {
dedupe: ['@fullcalendar/common'],
},
optimizeDeps: {
include: ['@fullcalendar/common'],
}

@nubcake94
Copy link

nubcake94 commented Mar 14, 2023

I can see that multiple people managed to solve this problem.
I've got a project in which I just can't seem to get it to work.

// package.json
// ...
"dependencies": {
   "svelte": "^3.55.0",
   "vite": "^4.0.4"
},
"devDependencies": {
   "svelte-fullcalendar": "^2.0.0-beta.0",
   "@fullcalendar/common": "^5",
   "@fullcalendar/core": "^5",
   "@fullcalendar/daygrid": "^5",
   "@fullcalendar/resource-timeline": "^5",
}
// vite.config.js
const config = {
	plugins: [sveltekit()],
	define: {
		'import.meta.env.VERCEL_ANALYTICS_ID': JSON.stringify(process.env.VERCEL_ANALYTICS_ID)
	},
	resolve: {
		dedupe: ['@fullcalendar/common']
	},
	optimizeDeps: {
		include: ['@fullcalendar/common']
	},
	target: '#svelte',
};

export default config;
// MyCalendar.svelte
<script lang="ts">
	import '@fullcalendar/core/vdom';
        /**
         ** Bunch of other imports in between, but my guess thats not the problem
         **/
	import daygridPlugin from '@fullcalendar/daygrid';
	import resourceTimelinePlugin from '@fullcalendar/resource-timeline';
	import FullCalendar from 'svelte-fullcalendar';

        let options = { /* it doesn't matter in this context*/ }
</script>

The error I get on built version (not dev) is the following:

(node:7740) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
D:\Work\Upwork\actwize\node_modules\@fullcalendar\core\vdom.js:1
import { __extends } from 'tslib';
^^^^^^

SyntaxError: Cannot use import statement outside a module

I tried every workaround mentioned above with no success :( Any idea how to resolve this issue?

@benlau6
Copy link

benlau6 commented Mar 16, 2023

@nubcake94 just stop using this library, use the latest fullcalendar instead. The fullcalendar team fixed the vdom problem.

// package.json
...
	"dependencies": {
		"@fullcalendar/common": "5.11.4",
		"@fullcalendar/core": "^6.1.4",
		"@fullcalendar/timegrid": "^6.1.4",
...
// vite.config.js
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite'

export default defineConfig({
  plugins: [sveltekit()]
});
// lib/FullCalendar.svelte component
<script lang="ts">
	import { onMount } from 'svelte';
	import { Calendar } from '@fullcalendar/core';
	import type { CalendarOptions } from '@fullcalendar/core';

	let classes: string | null = null;

	export { classes as class };

	export let style: string | null = null;

	export let options: CalendarOptions;

	export function getAPI() {
		return calendar;
	}

	let calendarEl: HTMLElement;
	let calendar: Calendar;

	onMount(async () => {
		if (!canBeInitiated) return;

		initCalendar();

		return () => {
			calendar && calendar.destroy();
		};
	});

	$: canBeInitiated =
		options && options.plugins && options.plugins.length && calendarEl && !calendar;

	$: {
		if (calendar && options && options.plugins && options.plugins.length) updateCalendarOptions();

		if (canBeInitiated) {
			initCalendar();
		}
	}

	function initCalendar() {
		calendar = new Calendar(calendarEl, options);
		calendar.render();
	}

	function updateCalendarOptions() {
		calendar.pauseRendering();
		calendar.resetOptions(options);
		calendar.resumeRendering();
	}
</script>

<div bind:this={calendarEl} class={classes} {style} />

Then you can use it with

// page.svelte
<script lang="ts">
  import FullCalendar from '$lib/FullCalendar.svelte';

  let calendarRef
  let options = {
    // some options
    ...
  }
</script>

<FullCalendar bind:this={calendarRef} {options} />

@nubcake94
Copy link

@nubcake94 just stop using this library, use the latest fullcalendar instead. The fullcalendar team fixed the vdom problem.

@benlau6 I'm really grateful for your suggestion, it works like a charm. I had so many other problems, like duplicated element appering when dropping external event to list, lagging, etc. It solved all my problems! Thanks 🤛🏻

@Afrowave
Copy link

Afrowave commented Mar 30, 2023

Dear @nubcake94 and @benlau6,

I am having the problem of the calendar is not rendering and there are no errors in the console at all. I followed all the above that @benlau6 laid out but I think my calendarRef and the options are not what I think they should be.

Is this the way it should look?

<script lang="ts">  
     import FullCalendar from '$lib/FullCalendar.svelte';  
     import daygridPlugin from '@fullcalendar/daygrid';  
     import timegridPlugin from '@fullcalendar/timegrid';

     let calendarRef = "dayGridMonth"  
     let options = {daygridPlugin}  
</script>

<section class="calendar">  
<FullCalendar bind:this={calendarRef} {options} />  
</section>  
<style>

</style> 

@kevinJread
Copy link

Hi - I was also getting frustrated with thsi Full Calender integration. I found a great alternative that is up to date wityh SvelteKit etc.

https://github.com/vkurko/calendar

@benmccann
Copy link
Contributor

fullcalendar 5 is horribly broken: https://publint.dev/@fullcalendar/core@5.0.0
fullcalendar 6 is fixed: https://publint.dev/@fullcalendar/core@6.0.0

This library needs to update its dependency

@benmccann
Copy link
Contributor

I look a stab at upgrading fullcalendar, but it didn't work because SvelteKit was on a beta version in this repo, so we need to update that first. I sent a PR for it here: #931

@YogliB
Copy link
Owner

YogliB commented Apr 20, 2023

@benmccann you're PR is merged.
if anyone wants to take on the package, you're welcome, I'm in a situation where I don't really have the time to maintain it...

@benmccann
Copy link
Contributor

Thank you! I've sent a fix here: #934

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

Successfully merging a pull request may close this issue.