Skip to content

Svelte example: upgrade from Svelte 4 to Svelte 5 runes - #8878

Open
pubkey wants to merge 1 commit into
masterfrom
claude/svelte-4-to-5-upgrade-fl47r1
Open

Svelte example: upgrade from Svelte 4 to Svelte 5 runes#8878
pubkey wants to merge 1 commit into
masterfrom
claude/svelte-4-to-5-upgrade-fl47r1

Conversation

@pubkey

@pubkey pubkey commented Jul 30, 2026

Copy link
Copy Markdown
Owner

This PR contains:

  • A BUGFIX
  • IMPROVED TESTS
  • IMPROVED DOCS
  • Dependency upgrade of examples/svelte

Describe the problem you have without this PR

examples/svelte was pinned to svelte@4.2.20. Svelte 5 has been the current major version since October 2024, so the example showed patterns that no longer match what a new Svelte app looks like: new App({ target }), svelte/store writables with $store auto-subscriptions, on:click handlers and a self-closing <textarea /> (which Svelte 5 rejects).

While migrating, the edit path turned out to be broken. NoteEditor called RxDocument.update() but store.js only added the query-builder and dev-mode plugins, so saving an already existing note threw you must add the update plugin. The old e2e test is named insert/edit/remove a note but never actually edited a note, so nothing caught it.

What changed

Svelte 5 migration

  • svelte 4.2.20 -> 5.56.8, plus runes: true in the compiler options of rollup.config.mjs so the example cannot fall back to legacy reactivity. rollup-plugin-svelte@7.2.3 already supports Svelte 5 and compiles .svelte.js rune modules, so the build setup stays as it is.
  • src/main.js mounts with mount(App, { target }) instead of new App({ target }).
  • src/store.js -> src/store.svelte.js. The four writables are replaced by one $state object plus selectNote() and resetForm() helpers. Components read and bind: to its fields directly, no $ prefix and no .set() calls.
  • NoteList.svelte subscribes to the RxDB query inside an $effect and returns a teardown that unsubscribes. The old onMount version never unsubscribed. The {#await} block around a plain array was replaced by a real loaded flag, and the {#each} is now keyed by the primary key.
  • on:click -> onclick, <textarea /> -> <textarea></textarea>.
  • Removed scripts/setupTypeScript.js, a leftover of the old sveltejs/template that pinned svelte-check@2 and svelte-preprocess@4. Nothing referenced it and both are incompatible with Svelte 5.

Bugfix

  • NoteEditor now uses the core incrementalPatch() instead of update(). It needs no extra plugin and retries on conflicts.
  • The title input is readonly while an existing note is edited, because name is the primaryKey of the schema and cannot change. Before this, editing the title of a saved note would have thrown even with the update plugin added.

Todos

  • Tests: added an e2e testcase that inserts a note, selects it, changes the body and verifies the note was updated instead of inserted twice. Verified npm run build plus the full e2e suite (2 passed) against a Chrome 141 headless run, and checked that all components and the rune module compile without warnings in dev: true, runes: true mode.
  • Documentation: examples/svelte/README.md lists where the runes are used.
  • Typings: not affected, the example is plain JavaScript.
  • Changelog: orga/changelog/svelte-example-svelte-5-runes.md

- svelte 4.2.20 -> 5.56.8 and enable `runes: true` in the compiler options
- main.js mounts the app with `mount()` instead of `new App()`
- store.js -> store.svelte.js, the shared writables are replaced by a
  `$state` object that the components read and bind to directly
- NoteList subscribes to the RxDB query inside an `$effect` and now
  unsubscribes when the component is destroyed
- `on:click` -> `onclick`, and `<textarea />` is closed properly

FIX saving an already existing note threw because `RxDocument.update()`
was used without adding the `update` plugin. The editor now uses the core
`incrementalPatch()` method, and the note title is readonly while an
existing note is edited because it is the primaryKey of the schema.

Adds an e2e testcase that edits an existing note, which is what
uncovered the broken save path.

Also removes `scripts/setupTypeScript.js`, a leftover of the old
sveltejs/template that pinned svelte-check 2 and svelte-preprocess 4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018i2Nta1aLFUMQgHEbaLdQa
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.

2 participants