rfw vs Vue, React, Svelte, An Honest Comparison
This comparison is written honestly. rfw is a newer framework with a smaller ecosystem. It has real strengths, type safety, single-language stack, fine-grained reactivity, built-in SSC, but also real gaps. Use this to decide whether rfw fits your project.
Philosophy
| Framework | Core idea |
|---|---|
| Vue | Progressive framework. Incrementally adoptable. Approachable reactivity with proxies. |
| React | UI as a function of state. Declarative rendering via virtual DOM diffing. Ecosystem-first. |
| Svelte | Compile away the framework. Minimal runtime. Reactive assignments are just variable mutations. |
| rfw | Single-language (Go) full-stack. Type-safe signals. Fine-grained DOM updates without virtual DOM. Server-Side Computed by default. |
Vue and React optimize for JavaScript ecosystem breadth. Svelte optimizes for minimal bundle size. rfw optimizes for type safety and server-integrated rendering in a single language.
Language
| Vue / React / Svelte | rfw | |
|---|---|---|
| Language | JavaScript / TypeScript | Go |
| Type safety | Opt-in via TypeScript; runtime type errors still possible | Mandatory; compiler enforces types at build time |
| Runtime errors | Common (undefined is not a function, etc.) | Rare, most caught at compile time |
| Server language | JS/TS (Node.js) or different language | Go, same as client |
| Shared types | Possible with TS isomorphic code | Built-in, same Go types on server and client |
| Interoperability | npm ecosystem (2M+ packages) | Go ecosystem + JS interop via js package |
Go’s type system catches what TypeScript can’t: exhaustive switch checks, nil pointer safety (with care), and struct field validation. But you lose access to npm packages on the client side. You can call JavaScript from WASM via the js interop layer, but it’s manual.
Bundle Size
| Framework | Typical client bundle | Notes |
|---|---|---|
| Vue | ~33 KB gzipped (runtime + compiler) | Smaller with production build |
| React | ~42 KB gzipped (react + react-dom) | Plus router, state lib |
| Svelte | ~2–10 KB gzipped | Compiler strips framework; per-component overhead is tiny |
| rfw | WASM binary (~1–5 MB compressed) | Go WASM binary includes runtime; Brotli compression helps |
rfw’s WASM bundle is significantly larger than any JS framework’s output. This is the primary performance trade-off. WASM initial download and parse time is higher, though execution speed can be faster after loading.
Mitigations: Brotli compression (.wasm.br), streaming compilation, SSC pre-renders content so users see HTML before WASM loads.
Reactivity Model
| Feature | Vue | React | Svelte | rfw |
|---|---|---|---|---|
| Mechanism | Proxy-based interception | Virtual DOM diffing | Compile-time tracking | Explicit signals |
| Granularity | Component-level re-render | Component-level re-render | DOM-level updates | DOM-level updates |
| State declaration | ref() / reactive() / computed() |
useState() / useReducer() |
let / $: |
*t.Int etc (type-based detection) |
| Mutation | Direct (proxied) | Immutable (setState) | Direct assignment | .Set() method |
| Read | Direct (proxied) | Variable read | Variable read | .Get() method |
| Derived state | computed() |
useMemo() |
$: |
Go methods / @expr: / state.Map() |
| Side effects | watch() / watchEffect() |
useEffect() |
$: reactive statements |
state.Effect() / OnMount() |
| Auto-tracking | Yes (proxy intercepts) | No (dependency array) | Yes (compiler) | No (explicit .Get() required) |
Svelte and Vue are more ergonomic, you just assign to variables. React is more explicit with setter functions and dependency arrays. rfw is the most explicit: every reactive read and write is a method call on a typed signal. This reduces accidental reactivity bugs at the cost of verbosity.
SSR / SSC
| Feature | Nuxt (Vue) | Next.js (React) | SvelteKit | rfw |
|---|---|---|---|---|
| SSR mode | Optional | Optional (SSR, SSG, ISR) | Optional | Required (SSC) |
| SPA fallback | Yes | Yes | Yes | No |
| Data fetching | useAsync / useFetch |
getServerSideProps / RSC |
load function |
Host component handler |
| Transport | HTTP (per request) | HTTP (per request) | HTTP (per request) | WebSocket (persistent) |
| Live updates | No (requires polling/SSE) | No (requires polling/SSE) | No (requires polling/SSE) | Yes (built-in via WebSocket) |
| Shared code | JS/TS isomorphic | JS/TS isomorphic | JS/TS isomorphic | Go (same types, same binary) |
| Hydration | HTML → Vue runtime | HTML → React runtime | HTML → Svelte runtime | HTML → WASM hydration |
| Server-side secrets | Must be careful (bundle leak risk) | Must be careful | Must be careful | Safe, server code never ships to client |
rfw’s SSC model is fundamentally different from SSR in JS frameworks. The persistent WebSocket enables real-time server-to-client updates without additional infrastructure. Server-side code is genuinely private, it never ships to the browser. The trade-off is that SSC is mandatory: there is no client-only mode.
Ecosystem Maturity
Be honest: this is rfw’s weakest area.
| Vue | React | Svelte | rfw | |
|---|---|---|---|---|
| npm/Go packages | 2M+ | 2M+ | Smaller subset | Go ecosystem + js interop |
| Component libraries | Vuetify, Element, Naive, etc. | MUI, Chakra, Ant Design | Smaller selection | None yet |
| UI frameworks | Many | Many | Fewer | Use Tailwind or custom CSS |
| DevTools | Vue DevTools (excellent) | React DevTools (excellent) | Svelte DevTools (basic) | Basic CLI debug mode |
| HMR | Vite (near-instant) | Fast Refresh (~1s) | Vite (~200ms) | rfw dev rebuild (seconds) |
| IDE support | Volar, Vetur | Built-in everywhere | Svelte for VS Code | Go LSP (excellent for Go) |
| Community size | Large | Very large | Growing | Small |
| Production usage | Widespread | Widespread | Growing | Early adopters |
| Learning resources | Extensive | Extensive | Good | Limited (this docs set) |
If you need rich UI component libraries or extensive third-party integrations, Vue or React are safer choices today.
Developer Experience
| Feature | Vue | React | Svelte | rfw |
|---|---|---|---|---|
| Setup | npm create vue |
create-react-app / Vite |
npm create svelte |
rfw init |
| Hot reload speed | Fast (~50ms) | Fast (~200ms) | Fast (~100ms) | Rebuild (~1–3s) |
| Type checking | TypeScript (opt-in) | TypeScript (opt-in) | TypeScript (opt-in) | Go compiler (mandatory) |
| Build time | ~1–5s | ~1–5s | ~1–3s | ~3–10s (WASM compilation) |
| Error messages | Good | Good | Good | Go compiler (very precise) |
| Debugging | Browser DevTools | Browser DevTools | Browser DevTools | rfw dev --debug + Go debugger |
| Testing | Vitest / Jest / Cypress | Jest / RTL / Cypress | Vitest / Cypress | Go testing package |
| Linting | ESLint | ESLint | ESLint | go vet / golangci-lint |
| Formatting | Prettier | Prettier | Prettier | gofmt (built-in) |
rfw’s HMR is slower than Vite-based JS frameworks because it must recompile Go to WASM on each change. The Go compiler’s error messages are excellent and catch issues JS frameworks only discover at runtime.
When to Choose rfw
Choose rfw if:
- Your team already writes Go and wants a single-language stack.
- Type safety is critical, you want compile-time guarantees, not runtime surprises.
- You need tight server-client integration with real-time updates (the WebSocket-first model fits dashboards, collaborative tools, live data).
- You want server-side secrets to never ship to the browser.
- You’re building an internal tool, dashboard, or data-heavy app where the larger WASM bundle is acceptable.
Stay with Vue/React/Svelte if:
- You need rich UI component libraries (data tables, date pickers, chart libraries).
- Your team doesn’t know Go and the learning curve isn’t worth it.
- Initial page load speed is critical and you need sub-100KB bundles.
- You rely heavily on npm packages for specific functionality (maps, editors, specialized widgets).
- You need a large hiring pool, Vue/React developers are far more available.
- You want progressive enhancement or client-only SPAs.
Consider migrating incrementally if:
- You have a Go backend and want to share types/validation with the frontend.
- You’re hitting TypeScript limitations (runtime type errors despite TS).
- You want to replace a complex SSR setup (Next.js/Nuxt) with a simpler, unified model.
Feature-by-Feature Comparison
| Feature | Vue | React | Svelte | rfw |
|---|---|---|---|---|
| Language | JS/TS | JS/TS | JS/TS | Go |
| Runtime model | Virtual DOM | Virtual DOM | No runtime (compiled) | Signals + WASM |
| Bundle size | Small | Medium | Tiny | Large (WASM) |
| Type safety | Opt-in (TS) | Opt-in (TS) | Opt-in (TS) | Mandatory (Go) |
| Reactivity | Proxy-based | State + diffing | Compiler-tracked | Explicit signals |
| DOM updates | Component-level | Component-level | DOM-level | DOM-level |
| SSR/SSC | Optional (Nuxt) | Optional (Next.js) | Optional (SvelteKit) | Required (SSC) |
| Server-client transport | HTTP | HTTP | HTTP | WebSocket |
| Live server updates | No (extra infra) | No (extra infra) | No (extra infra) | Yes (built-in) |
| Same language server/client | Yes (Node) | Yes (Node) | Yes (Node) | Yes (Go) |
| Shared types | Yes (TS isomorphic) | Yes (TS isomorphic) | Yes (TS isomorphic) | Yes (Go, no serialization) |
| Scoped CSS | Yes | Yes (CSS Modules) | Yes (built-in) | No (external) |
| Component libraries | Many | Many | Few | None yet |
| DevTools | Excellent | Excellent | Basic | Basic |
| HMR speed | Fast | Fast | Fast | Slow (recompile) |
| Testing frameworks | Many | Many | Several | Go testing |
| Ecosystem size | Large | Very large | Medium | Small |
| Production readiness | Widespread | Widespread | Growing | Early |
| Form handling | Manual / libraries | Manual / libraries | bind: + enhance |
@signal:..:w + host |
| Routing | vue-router | react-router / Next.js | SvelteKit | router.Page/Group |
| State management | Pinia / Vuex | Redux / Zustand / Jotai | Stores | signals + state.Store |
| DI | provide/inject | Context | setContext/getContext | *t.Inject[T] + Container |
| i18n | vue-i18n | react-i18next | svelte-i18n | rfw i18n plugin |
| SEO | Nuxt SSR | Next.js SSR | SvelteKit SSR | SSC (built-in) |
| Mobile | Capacitive / NativeScript | React Native | Svelte Native | Not supported |
Summary
rfw trades:
- Ecosystem breadth for type safety
- Bundle size for a single-language stack
- HMR speed for compile-time guarantees
- UI library availability for server-integrated rendering
- Community size for Go-based simplicity
If these trades align with your priorities, especially if you’re a Go team building data-rich applications, rfw is worth evaluating. If you need the ecosystem, the fast HMR, or the tiny bundles, Vue/React/Svelte remain the pragmatic choice.