Open6
Svelte 5 マイグレーションメモ
Svelte 4 => 5 をする際のメモ。
マイグレーションスクリプトがあるので基本的にはそれを実行すれば良さそうだが破壊的変更もありそうな雰囲気。
懸念点
聞いた話。
-
Map
=>SvelteMap
-
SvelteMap
はset
の度に変更が検知される?- 最後にまとめて更新ができない
-
-
$:
が無限ループになる?
マイグレーションスクリプト
npx sv migrate svelte-5
npm install
Nostr hours
diff --git a/package.json b/package.json
index a2500c8..080c7c8 100644
--- a/package.json
+++ b/package.json
@@ -18,21 +18,21 @@
"@playwright/test": "^1.28.1",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-static": "^3.0.1",
- "@sveltejs/kit": "^2.0.0",
+ "@sveltejs/kit": "^2.5.27",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-svelte": "^2.36.0-next.4",
+ "eslint-plugin-svelte": "^2.45.1",
"prettier": "^3.1.1",
- "prettier-plugin-svelte": "^3.1.2",
- "svelte": "^5.0.0-next.1",
+ "prettier-plugin-svelte": "^3.2.6",
+ "svelte": "^5.0.0",
"svelte-check": "^4.0.5",
"tslib": "^2.4.1",
- "typescript": "^5.0.0",
- "vite": "^5.0.3",
+ "typescript": "^5.5.0",
+ "vite": "^5.4.4",
"vitest": "^2.1.3"
},
"type": "module",
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 7ef5dad..0bebbaa 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,4 +1,14 @@
-<main><slot /></main>
+<script>
+ /**
+ * @typedef {Object} Props
+ * @property {import('svelte').Snippet} [children]
+ */
+
+ /** @type {Props} */
+ let { children } = $props();
+</script>
+
+<main>{@render children?.()}</main>
<style>
main {
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index df09a48..2ab4ec3 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,4 +1,7 @@
<script lang="ts">
+ import { run, createBubbler, preventDefault } from 'svelte/legacy';
+
+ const bubble = createBubbler();
import { onMount } from 'svelte';
import { NostrFetcher } from 'nostr-fetch';
import { nip19 } from 'nostr-tools';
@@ -6,14 +9,14 @@
import { browser } from '$app/environment';
import { page } from '$app/stores';
- let npub = '';
- let metadata: Content.Metadata | undefined;
- let events: Event[] = [];
+ let npub = $state('');
+ let metadata: Content.Metadata | undefined = $state();
+ let events: Event[] = $state([]);
const defaultRelays = ['wss://relay.nostr.band/', 'wss://nos.lol/'];
const days = 14;
- let displayEventCount = false;
- let displayGradation = false;
+ let displayEventCount = $state(false);
+ let displayGradation = $state(false);
const now = new Date();
const dates = Array.from({ length: days }, (_, i) => {
@@ -23,18 +26,6 @@
});
const hours = Array.from({ length: 24 }, (_, i) => i);
- $: if (npub.startsWith('npub1') && browser) {
- console.log(npub);
- try {
- const { type, data: pubkey } = nip19.decode(npub);
- if (type === 'npub') {
- metadata = undefined;
- events = [];
- fetch(pubkey);
- history.replaceState(history.state, '', `${$page.url.pathname}?npub=${npub}`);
- }
- } catch (error) {}
- }
onMount(() => {
npub = $page.url.searchParams.get('npub') ?? '';
@@ -148,33 +139,49 @@
return `rgb(${red}, ${green}, ${blue})`;
}
- let eventsCountPerHour: number[][] = [];
+ let eventsCountPerHour: number[][] = $state([]);
- $: eventsCountPerHour = dates.map((date) =>
- hours.map(
- (hour) =>
- events.filter((event) => {
- const createdAt = event.created_at * 1000;
- return (
- date.getTime() + hour * 60 * 60 * 1000 <= createdAt &&
- createdAt < date.getTime() + (hour + 1) * 60 * 60 * 1000
- );
- }).length
- )
- );
function totalEventsForDate(index: number) {
return eventsCountPerHour[index] ? eventsCountPerHour[index].reduce((a, b) => a + b, 0) : 0;
}
+ run(() => {
+ if (npub.startsWith('npub1') && browser) {
+ console.log(npub);
+ try {
+ const { type, data: pubkey } = nip19.decode(npub);
+ if (type === 'npub') {
+ metadata = undefined;
+ events = [];
+ fetch(pubkey);
+ history.replaceState(history.state, '', `${$page.url.pathname}?npub=${npub}`);
+ }
+ } catch (error) {}
+ }
+ });
+ run(() => {
+ eventsCountPerHour = dates.map((date) =>
+ hours.map(
+ (hour) =>
+ events.filter((event) => {
+ const createdAt = event.created_at * 1000;
+ return (
+ date.getTime() + hour * 60 * 60 * 1000 <= createdAt &&
+ createdAt < date.getTime() + (hour + 1) * 60 * 60 * 1000
+ );
+ }).length
+ )
+ );
+ });
</script>
<h1>Nostr hours</h1>
<p>How many hours do you spend in Nostr?</p>
-<form on:submit|preventDefault>
+<form onsubmit={preventDefault(bubble('submit'))}>
<div>
<input type="text" bind:value={npub} placeholder="npub1..." />
- <input type="button" on:click={inputNpub} value="from NIP-07" />
+ <input type="button" onclick={inputNpub} value="from NIP-07" />
</div>
<div>
マイグレーションスクリプトは問題なく実行できたが、npm update
後 npm outdated
で残っているものを更新しようとしたら一部依存関係を解決できなかった。
> npm install @sveltejs/vite-plugin-svelte@latest vite@latest
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: nostr-hours@0.0.1
npm ERR! Found: @sveltejs/vite-plugin-svelte@4.0.2
npm ERR! node_modules/@sveltejs/vite-plugin-svelte
npm ERR! peer @sveltejs/vite-plugin-svelte@"^3.0.0 || ^4.0.0-next.1 || ^5.0.0" from @sveltejs/kit@2.9.0
npm ERR! node_modules/@sveltejs/kit
npm ERR! peer @sveltejs/kit@"^2.0.0" from @sveltejs/adapter-auto@3.3.1
npm ERR! node_modules/@sveltejs/adapter-auto
npm ERR! dev @sveltejs/adapter-auto@"^3.0.0" from the root project
npm ERR! peer @sveltejs/kit@"^2.0.0" from @sveltejs/adapter-static@3.0.6
npm ERR! node_modules/@sveltejs/adapter-static
npm ERR! dev @sveltejs/adapter-static@"^3.0.1" from the root project
npm ERR! 1 more (the root project)
npm ERR! peer @sveltejs/vite-plugin-svelte@"^4.0.0-next.0||^4.0.0" from @sveltejs/vite-plugin-svelte-inspector@3.0.1
npm ERR! node_modules/@sveltejs/vite-plugin-svelte-inspector
npm ERR! @sveltejs/vite-plugin-svelte-inspector@"^3.0.0-next.0||^3.0.0" from @sveltejs/vite-plugin-svelte@4.0.2
npm ERR! 1 more (the root project)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev @sveltejs/vite-plugin-svelte@"5.0.1" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: vite@6.0.1
npm ERR! node_modules/vite
npm ERR! peer vite@"^6.0.0" from @sveltejs/vite-plugin-svelte@5.0.1
npm ERR! node_modules/@sveltejs/vite-plugin-svelte
npm ERR! dev @sveltejs/vite-plugin-svelte@"5.0.1" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR!
npm ERR! For a full report see:
npm ERR! C:\Users\SnowCait\AppData\Local\npm-cache\_logs\2024-12-01T08_35_06_987Z-eresolve-report.txt
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\SnowCait\AppData\Local\npm-cache\_logs\2024-12-01T08_35_06_987Z-debug-0.log
$state
に置き換わることでパフォーマンスが劣化した。
内部的に Proxy
が使われているようなのでおそらく更新頻度が高い Array.push に使うと重い。
$state.raw
にして代入で更新するようにすると改善された。
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index abb4053..2304d92 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -11,7 +11,7 @@
let npub = $state('');
let metadata: Content.Metadata | undefined = $state();
- let events: Event[] = $state([]);
+ let events: Event[] = $state.raw([]);
const defaultRelays = ['wss://relay.nostr.band/', 'wss://nos.lol/'];
const days = 14;
@@ -84,7 +84,7 @@
);
for await (const event of iterator) {
console.log(event);
- events.push(event);
- events = events;
+ events = [...events, event];
}
}
@render
対応で <script />
がなかったコンポーネントに追加されることがあるが言語が JS になっているので TS に変更する必要がある。(TS プロジェクトの場合)
$:
が svelte/legacy
の run
に置き換えられるが $derived
と $effect
に修正できるとベター。