[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
---
|
||||
id: frontend-vue3-svelte5-patterns
|
||||
title: Vue 3 / Svelte 5 — modern composition / runes
|
||||
category: Coding
|
||||
status: draft
|
||||
source_trust_level: B
|
||||
verification_status: conceptual
|
||||
created_at: 2026-05-09
|
||||
updated_at: 2026-05-09
|
||||
tags: [frontend, vue, svelte, vibe-coding]
|
||||
tech_stack: { language: "TS", applicable_to: ["Frontend"] }
|
||||
applied_in: []
|
||||
aliases: [Vue 3, Composition API, Pinia, Svelte 5, runes, $state, Nuxt, SvelteKit]
|
||||
---
|
||||
|
||||
# Vue 3 / Svelte 5
|
||||
|
||||
> React 의 alternative. **Vue 3 (composition API), Svelte 5 (runes — signal식)**. Modern reactivity.
|
||||
|
||||
## 📖 핵심 개념
|
||||
- Vue: composition API (React hooks 비슷).
|
||||
- Svelte 5: runes (signal-based).
|
||||
- 둘 다 modern reactivity.
|
||||
- SSR 친화 (Nuxt, SvelteKit).
|
||||
|
||||
## 💻 코드 패턴
|
||||
|
||||
### Vue 3 SFC (Single File Component)
|
||||
```vue
|
||||
<script setup lang='ts'>
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
const count = ref(0);
|
||||
const double = computed(() => count.value * 2);
|
||||
|
||||
function increment() {
|
||||
count.value++;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click='increment'>{{ count }} ({{ double }})</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
button { padding: 8px; }
|
||||
</style>
|
||||
```
|
||||
|
||||
→ Template + script + style.
|
||||
|
||||
### Vue Composition API
|
||||
```ts
|
||||
import { ref, reactive, computed, watch, onMounted } from 'vue';
|
||||
|
||||
const count = ref(0); // primitive
|
||||
const user = reactive({ name: '' }); // object
|
||||
const double = computed(() => count.value * 2);
|
||||
|
||||
watch(count, (newVal, oldVal) => {
|
||||
console.log('count:', newVal);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
console.log('mounted');
|
||||
});
|
||||
```
|
||||
|
||||
→ React hooks 비슷.
|
||||
|
||||
### Vue composable (custom hook)
|
||||
```ts
|
||||
// composables/useCounter.ts
|
||||
export function useCounter(initial = 0) {
|
||||
const count = ref(initial);
|
||||
const inc = () => count.value++;
|
||||
return { count, inc };
|
||||
}
|
||||
|
||||
// 사용
|
||||
const { count, inc } = useCounter();
|
||||
```
|
||||
|
||||
### Pinia (Vue 의 Zustand)
|
||||
```ts
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => ({ name: '', age: 0 }),
|
||||
actions: {
|
||||
setName(name: string) { this.name = name; },
|
||||
},
|
||||
getters: {
|
||||
isAdult: (state) => state.age >= 18,
|
||||
},
|
||||
});
|
||||
|
||||
// 사용
|
||||
const store = useUserStore();
|
||||
store.setName('Alice');
|
||||
console.log(store.isAdult);
|
||||
```
|
||||
|
||||
### Nuxt (Vue 의 Next)
|
||||
```vue
|
||||
<!-- pages/users/[id].vue -->
|
||||
<script setup>
|
||||
const route = useRoute();
|
||||
const { data } = await useFetch(`/api/users/${route.params.id}`);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ data.name }}</h1>
|
||||
</template>
|
||||
```
|
||||
|
||||
→ File-based route + SSR/SSG/edge.
|
||||
|
||||
### Svelte 5 (runes)
|
||||
```svelte
|
||||
<script>
|
||||
let count = $state(0);
|
||||
let double = $derived(count * 2);
|
||||
|
||||
$effect(() => {
|
||||
console.log('count:', count);
|
||||
});
|
||||
|
||||
function increment() {
|
||||
count++;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={increment}>{count} ({double})</button>
|
||||
|
||||
<style>
|
||||
button { padding: 8px; }
|
||||
</style>
|
||||
```
|
||||
|
||||
→ `$state` / `$derived` / `$effect` = runes.
|
||||
|
||||
### Svelte 5 의 변화
|
||||
```
|
||||
Svelte 4: implicit reactivity (let, $:).
|
||||
Svelte 5: explicit ($state, $derived).
|
||||
|
||||
→ 더 명시적. Compile-time.
|
||||
```
|
||||
|
||||
### SvelteKit (Svelte 의 Next)
|
||||
```svelte
|
||||
<!-- routes/users/[id]/+page.svelte -->
|
||||
<script>
|
||||
let { data } = $props();
|
||||
</script>
|
||||
|
||||
<h1>{data.name}</h1>
|
||||
```
|
||||
|
||||
```ts
|
||||
// routes/users/[id]/+page.server.ts
|
||||
export async function load({ params }) {
|
||||
const user = await fetchUser(params.id);
|
||||
return { name: user.name };
|
||||
}
|
||||
```
|
||||
|
||||
### Vue vs React vs Svelte
|
||||
```
|
||||
Vue:
|
||||
- Template (HTML-friendly).
|
||||
- Composition API (modern).
|
||||
- 큰 ecosystem.
|
||||
- Pinia / Vue Router.
|
||||
|
||||
Svelte:
|
||||
- Compile-time (no runtime VDOM).
|
||||
- 작은 bundle.
|
||||
- Beautiful syntax.
|
||||
- Smaller ecosystem.
|
||||
|
||||
React:
|
||||
- 가장 큰 ecosystem.
|
||||
- Compiler (modern).
|
||||
- JSX (TS-friendly).
|
||||
```
|
||||
|
||||
→ 다 좋음. Team 의 선호.
|
||||
|
||||
### Vue 의 reactivity caveat
|
||||
```ts
|
||||
const obj = reactive({ count: 0 });
|
||||
|
||||
// ❌ Lost reactivity
|
||||
const { count } = obj;
|
||||
count++; // 안 trigger.
|
||||
|
||||
// ✅ Use ref
|
||||
const count = ref(0);
|
||||
// 또는
|
||||
import { toRefs } from 'vue';
|
||||
const { count } = toRefs(obj);
|
||||
```
|
||||
|
||||
→ Destructure 가 lose reactivity.
|
||||
|
||||
### Svelte 5 의 reactive store
|
||||
```svelte
|
||||
<script>
|
||||
// global state file (state.svelte.ts)
|
||||
export const userStore = $state({ name: '' });
|
||||
|
||||
// 사용
|
||||
$effect(() => {
|
||||
console.log(userStore.name);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
→ Global signal 식.
|
||||
|
||||
### Vue v-model (two-way)
|
||||
```vue
|
||||
<input v-model='message' />
|
||||
<!-- 동등 -->
|
||||
<input :value='message' @input='message = $event.target.value' />
|
||||
```
|
||||
|
||||
→ Two-way binding 가 native.
|
||||
|
||||
### Vue Teleport (portal)
|
||||
```vue
|
||||
<Teleport to='body'>
|
||||
<div class='modal'>...</div>
|
||||
</Teleport>
|
||||
```
|
||||
|
||||
→ React Portal 비슷.
|
||||
|
||||
### Suspense
|
||||
```vue
|
||||
<Suspense>
|
||||
<template #default>
|
||||
<AsyncComponent />
|
||||
</template>
|
||||
<template #fallback>
|
||||
<Loading />
|
||||
</template>
|
||||
</Suspense>
|
||||
```
|
||||
|
||||
### Lifecycle (Vue)
|
||||
```ts
|
||||
import { onMounted, onUnmounted, onUpdated } from 'vue';
|
||||
|
||||
onMounted(() => { ... });
|
||||
onUnmounted(() => { ... });
|
||||
onUpdated(() => { ... });
|
||||
```
|
||||
|
||||
### Lifecycle (Svelte 5)
|
||||
```svelte
|
||||
<script>
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
|
||||
onMount(() => {
|
||||
return () => { /* cleanup */ };
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Production
|
||||
```
|
||||
Vue:
|
||||
- Alibaba, Tencent (China).
|
||||
- Nuxt site / blog.
|
||||
- Enterprise admin.
|
||||
|
||||
Svelte:
|
||||
- The New York Times.
|
||||
- Apple Music (옛).
|
||||
- Brave browser.
|
||||
```
|
||||
|
||||
### Migration from React
|
||||
```
|
||||
Vue:
|
||||
- API 가 비슷 (composition).
|
||||
- Template 다름.
|
||||
- Pinia ≈ Zustand.
|
||||
- Nuxt ≈ Next.
|
||||
|
||||
Svelte:
|
||||
- 더 다름.
|
||||
- 작은 bundle.
|
||||
- 새 mental model.
|
||||
|
||||
→ Vue 가 React → migration 가 부드러움.
|
||||
```
|
||||
|
||||
### Performance
|
||||
```
|
||||
Svelte: 가장 빠름 (compile-time).
|
||||
Vue 3: 빠름 (reactivity).
|
||||
React + Compiler: 빠름.
|
||||
|
||||
→ 매 framework 가 modern.
|
||||
```
|
||||
|
||||
### LLM 도움
|
||||
```
|
||||
Vue / Svelte 의 docs 가 LLM 에 baked.
|
||||
- Component 작성 OK.
|
||||
- 작은 ecosystem 의 niche library 가 약.
|
||||
|
||||
→ React 보다 정확도 약간 ↓.
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준
|
||||
| 상황 | 추천 |
|
||||
|---|---|
|
||||
| 큰 ecosystem | React |
|
||||
| 작은 bundle | Svelte |
|
||||
| HTML-friendly | Vue |
|
||||
| China market | Vue |
|
||||
| Beautiful code | Svelte |
|
||||
| Modern team | 매 다 OK |
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Vue reactive destructure**: lost.
|
||||
- **Svelte 4 → 5 mix runes**: 깨짐.
|
||||
- **Library 가 React-only**: lock-in.
|
||||
- **Mixed framework**: complexity.
|
||||
|
||||
## 🤖 LLM 활용 힌트
|
||||
- Vue 3 composition API 가 modern.
|
||||
- Svelte 5 runes = signal-based.
|
||||
- Pinia / Nuxt / SvelteKit = ecosystem.
|
||||
- React + Compiler 와 수렴.
|
||||
|
||||
## 🔗 관련 문서
|
||||
- [[Frontend_SolidJS_Qwik]]
|
||||
- [[Frontend_React_Compiler_Deep]]
|
||||
- [[Frontend_State_Management_Modern]]
|
||||
Reference in New Issue
Block a user