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

Support Svelte 5 Runes mode #51

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Conversation

kvangrae
Copy link

This pull request provides support for Svelte 5 runes mode. It is not backwards compatible for Svelte 4.

Summary of changes:

  • Dependencies have been upgraded to support Svelte 5.
  • Compiler has been set to Runes mode.
  • Code updated to use runes.

Closes #48

src/Time.svelte Outdated

import { dayjs } from "./dayjs";
import { onMount } from "svelte";

/** @type {undefined | NodeJS.Timeout} */
let interval = undefined;
let liveUpdate = $state(0);

const DEFAULT_INTERVAL = 60 * 1_000;

onMount(() => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should be called onDestroy https://svelte.dev/docs/svelte/lifecycle-hooks

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually would be better to move it into $effect

$effect(() => {
		// This will be recreated whenever `milliseconds` changes
		const interval = setInterval(() => {
			count += 1;
		}, milliseconds);

		return () => {
			// if a callback is provided, it will run
			// a) immediately before the effect re-runs
			// b) when the component is destroyed
			clearInterval(interval);
		};
	});
	```

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. that should be easy. i'll have a look tomorrow.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have updated the code to return the clearInterval in $effect return statement.

Copy link

@niemyjski niemyjski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I think we could clean up the onmount and use the function return of $effect

@niemyjski
Copy link

cc @metonym

src/Time.svelte Outdated

import { dayjs } from "./dayjs";
import { onMount } from "svelte";

/** @type {undefined | NodeJS.Timeout} */
let interval = undefined;
let liveUpdate = $state(0);

const DEFAULT_INTERVAL = 60 * 1_000;

onMount(() => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. that should be easy. i'll have a look tomorrow.

src/Time.svelte Outdated
Comment on lines 62 to 65
let formatted = $derived.by(() => {
liveUpdate; // no-op. this is a dependency trigger for live updates
return relative ? dayjs(timestamp).from() : dayjs(timestamp).format(format);
});
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that we need the liveUpdate $state rune b/c if any of the props change, formatted should get updated (i think...). it is something i can test. if not, this would simplify some things.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have removed liveUpdate as it does not have any adverse impacts on live updates.

Comment on lines +39 to 51
$effect(() => {
/** @type {undefined | NodeJS.Timeout} */
let interval;
if (relative && live !== false) {
interval = setInterval(
() => {
formatted = dayjs(timestamp).from();
},
Math.abs(typeof live === "number" ? live : DEFAULT_INTERVAL),
);
}
return () => clearInterval(interval);
});
Copy link

@niemyjski niemyjski Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait how does this even work. If this is setting formatted, but formatted is derived. Guessing this one takes over the derived instance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call. it does work, but i agree, it doesn't makes sense for me to update a derived value. i'm thinking formatted should be a $state instead of a $derived. if that makes sense, let me know and i will update.

but, in this instance, the derived will only be updated if relative, live, or timestamp ever change, which, most likely, they won't change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either is fine, I think that if we update it the initial state needs to be set in the effect?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i found that in $effect any values that are read asynchronously, for example in a setInterval, will not be tracked.

https://svelte.dev/docs/svelte/$effect#Understanding-dependencies

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, it doesn't look like it is recommended to set the initial state inside of the $effect. my intellij complains with the following:
image

Copy link
Author

@kvangrae kvangrae Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with what i found out above, i'm thinking to either keep it the way it is or change formatted to use $state instead of $derived. let me know your thoughts.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably using state would be good, whatever keeps it simple and easy to understand

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link

@niemyjski niemyjski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, left one comment.

@niemyjski
Copy link

@metonym can we get a new release and this merged? Is there anything else that should be updated like Dayjs?

@metonym
Copy link
Owner

metonym commented Dec 15, 2024

Nice work, thanks both.

Will review – I think one thing that'll need updating is the demo, for which it breaks entirely for Svelte 5. It could be a nice opportunity to switch to Vite instead of Rollup.

@niemyjski
Copy link

@metonym can we get this merged and that gets followed up on?

… a svelte field in their package.json but no exports condition for svelte.

svelte-time@0.9.0

Please see https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition for details.
@kvangrae
Copy link
Author

Nice work, thanks both.

Will review – I think one thing that'll need updating is the demo, for which it breaks entirely for Svelte 5. It could be a nice opportunity to switch to Vite instead of Rollup.

I've updated and ran the examples. I could successfully run and verify sveltekit and vite. I ran into issues with the following examples:

  • rollup - npm run dev I couldn't find what port it was running on to verify. I was expecting it to be running on default port 5000.
  • webpack - npm run dev complains "Module not found: Error: Package path . is not exported from package". I'm not good with webpack and wasn't sure exactly how to resolve it.

Any help would be appreciated.

package.json Outdated
".": {
"svelte": "./src/index.js"
}
},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exports condition is not needed, as it's dynamically generated.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed. i originally added it due to a compiler warning

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

Successfully merging this pull request may close these issues.

Cannot use $$restProps in runes mode (Svelte 5)
3 participants