Svelte 5上手实测:对比Vue/React的真实差距
发布日期: 2026/08/15 阅读总量: 0

一、真实场景:一个让我失眠的React项目

2024年11月,我接手了一个内部工单管理系统。React 16 + Redux + React Router,2.4万行代码。项目跑起来浏览器标签页占用内存1.2GB。打包产物gzip后285KB,首屏在低端机器上要3秒以上。用户天天抱怨,产品经理天天催。

我用Chrome Performance面板测了性能数据,单次渲染500条工单列表需要640ms。什么概念?用户每点一次筛选按钮,页面白屏半秒以上。这是React 16的典型症状——父组件setState后整棵子树重新协调。

我当时的选项有三个:继续用React但全面重构到React 18/19;迁移到Vue 3;换用Svelte 5。我用一个调研工单卡片组件做了对比验证。下面是我实测的全过程。

二、方案对比:为什么最终选了Svelte

维度React 18.3.1Vue 3.5.12Svelte 5.1.9
运行时体积(gzip)约42KB(react+react-dom)约34KB(vue 完整版)约12KB(不含编译器)
响应式原理虚拟DOM + 协调响应式代理(Proxy)编译时处理器+信号(signals)
学习成本中(hooks规则多)低(模板语法直观)低(类似Vue但更少API)
细粒度更新否,组件级是,组件级+细粒度是,变量级
TypeScript支持优秀良好优秀(原生支持)
构建工具Vite 6.0.3Vite 6.0.3Vite 6.0.3(官方推荐)

关键差距在运行时。React和Vue都在浏览器里做了大量工作:React的Fiber协调机制,Vue的Proxy劫持。Svelte 5把编译器放到构建阶段,直接生成原生DOM操作代码,没有虚拟DOM这一层。

Svelte 5最核心的变化是引入了runes——一组编译器层面的响应式原语。这不是又一个状态管理库,它是Svelte语言的组成部分。$state$derived$effect这些符号直接进编译器。

三、同一个组件,三套代码的实录

3.1 需求描述

一个工单卡片组件,功能:

  • 展示工单标题、状态、优先级
  • 点击「处理」按钮后工单状态变为「处理中」
  • 点击「完成」按钮后状态变为「已完成」并显示完成时间
  • 当工单优先级为「高」时,卡片左侧显示红色竖条

3.2 React 18 实现(使用函数组件和hooks)

// React 18.3.1, 使用 TypeScript 5.6.2
import React, { useState, useCallback } from 'react';

type TicketStatus = 'pending' | 'processing' | 'done';
type Priority = 'low' | 'medium' | 'high';

interface TicketCardProps {
  title: string;
  priority: Priority;
}

export default function TicketCard({ title, priority }: TicketCardProps) {
  const [status, setStatus] = useState('pending');
  const [completedAt, setCompletedAt] = useState(null);

  const handleProcess = useCallback(() => {
    setStatus('processing');
  }, []);

  const handleComplete = useCallback(() => {
    setStatus('done');
    setCompletedAt(new Date().toLocaleString('zh-CN'));
  }, []);

  return (
    <div className={`ticket-card priority-${priority}`}>
      {priority === 'high' && <span className="high-indicator" />}
      <h3>{title}</h3>
      <p>状态:{status}</p>
      {status === 'done' && completedAt ? (
        <p>完成时间:{completedAt}</p>
      ) : (
        <div className="actions">
          <button onClick={handleProcess} disabled={status !== 'pending'}>
            处理
          </button>
          <button onClick={handleComplete} disabled={status === 'done'}>
            完成
          </button>
        </div>
      )}
    </div>
  );
}

3.3 Vue 3 实现(使用