发布于

Svelte 框架深度解析:编译时优化的现代前端框架完全指南

作者

Svelte 框架深度解析:编译时优化的现代前端框架完全指南

Svelte 是一个革命性的前端框架,它通过编译时优化生成高效的原生 JavaScript 代码,无需虚拟 DOM,提供了出色的性能和开发体验。本文将深入探讨 Svelte 的核心特性和实际应用。

Svelte 核心概念

什么是 Svelte

Svelte 是一个编译时框架,它将组件编译为高效的原生 JavaScript 代码:

<!-- App.svelte -->
<script>
  let count = 0;
  
  function increment() {
    count += 1;
  }
  
  // 响应式声明
  $: doubled = count * 2;
  $: if (count >= 10) {
    alert('count is dangerously high!');
  }
</script>

<h1>Hello Svelte!</h1>
<p>Count: {count}</p>
<p>Doubled: {doubled}</p>

<button on:click={increment}>
  Click me
</button>

<style>
  h1 {
    color: #ff3e00;
    text-transform: uppercase;
    font-size: 4em;
    font-weight: 100;
  }
  
  button {
    background: #ff3e00;
    color: white;
    border: none;
    padding: 1em 2em;
    border-radius: 0.5em;
    cursor: pointer;
    font-size: 1.2em;
  }
  
  button:hover {
    background: #ff5722;
  }
</style>

响应式系统

<!-- Reactivity.svelte -->
<script>
  let firstName = 'John';
  let lastName = 'Doe';
  
  // 响应式声明 - 自动重新计算
  $: fullName = `${firstName} ${lastName}`;
  $: initials = `${firstName[0]}${lastName[0]}`;
  
  // 响应式语句 - 副作用
  $: console.log('Full name changed:', fullName);
  
  // 响应式块 - 复杂逻辑
  $: {
    console.log('Name components changed');
    if (firstName && lastName) {
      document.title = fullName;
    }
  }
  
  let numbers = [1, 2, 3, 4, 5];
  
  // 数组响应式
  $: sum = numbers.reduce((a, b) => a + b, 0);
  $: average = sum / numbers.length;
  
  function addNumber() {
    // 触发响应式更新
    numbers = [...numbers, numbers.length + 1];
  }
  
  function removeNumber() {
    numbers = numbers.slice(0, -1);
  }
  
  // 对象响应式
  let person = {
    name: 'Alice',
    age: 30,
    hobbies: ['reading', 'coding']
  };
  
  $: personInfo = `${person.name} is ${person.age} years old`;
  
  function updatePerson() {
    // 重新赋值触发更新
    person = {
      ...person,
      age: person.age + 1
    };
  }
  
  function addHobby() {
    // 数组更新
    person.hobbies = [...person.hobbies, 'swimming'];
  }
</script>

<div class="container">
  <section>
    <h2>Basic Reactivity</h2>
    <input bind:value={firstName} placeholder="First name" />
    <input bind:value={lastName} placeholder="Last name" />
    <p>Full name: <strong>{fullName}</strong></p>
    <p>Initials: <strong>{initials}</strong></p>
  </section>
  
  <section>
    <h2>Array Reactivity</h2>
    <p>Numbers: {numbers.join(', ')}</p>
    <p>Sum: {sum}</p>
    <p>Average: {average.toFixed(2)}</p>
    <button on:click={addNumber}>Add Number</button>
    <button on:click={removeNumber}>Remove Number</button>
  </section>
  
  <section>
    <h2>Object Reactivity</h2>
    <p>{personInfo}</p>
    <p>Hobbies: {person.hobbies.join(', ')}</p>
    <button on:click={updatePerson}>Age +1</button>
    <button on:click={addHobby}>Add Hobby</button>
  </section>
</div>

<style>
  .container {
    max-width: 800px;
    margin: 0 auto;
    padding: 2rem;
  }
  
  section {
    margin-bottom: 2rem;
    padding: 1rem;
    border: 1px solid #ddd;
    border-radius: 0.5rem;
  }
  
  input {
    margin: 0.5rem;
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 0.25rem;
  }
  
  button {
    margin: 0.25rem;
    padding: 0.5rem 1rem;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 0.25rem;
    cursor: pointer;
  }
  
  button:hover {
    background: #0056b3;
  }
</style>

组件通信

<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
  import EventChild from './EventChild.svelte';
  
  let parentMessage = 'Hello from parent';
  let childData = '';
  
  // 处理子组件事件
  function handleChildEvent(event) {
    console.log('Received from child:', event.detail);
    childData = event.detail.message;
  }
  
  // 使用 bind 双向绑定
  let sharedValue = 'Shared data';
  
  // 插槽内容
  let showAdvanced = false;
</script>

<div class="parent">
  <h1>Parent Component</h1>
  
  <!-- Props 传递 -->
  <Child message={parentMessage} count={42} />
  
  <!-- 事件处理 -->
  <EventChild on:custom={handleChildEvent} />
  {#if childData}
    <p>Data from child: {childData}</p>
  {/if}
  
  <!-- 双向绑定 -->
  <Child bind:value={sharedValue} />
  <p>Shared value: {sharedValue}</p>
  
  <!-- 插槽使用 -->
  <Child>
    <h3 slot="header">Custom Header</h3>
    <p>This is slot content</p>
    {#if showAdvanced}
      <div slot="footer">
        <button>Advanced Action</button>
      </div>
    {/if}
  </Child>
  
  <button on:click={() => showAdvanced = !showAdvanced}>
    Toggle Advanced
  </button>
</div>

<style>
  .parent {
    padding: 2rem;
    border: 2px solid #007bff;
    border-radius: 0.5rem;
  }
</style>
<!-- Child.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  
  // Props
  export let message = 'Default message';
  export let count = 0;
  export let value = '';
  
  // 事件分发器
  const dispatch = createEventDispatcher();
  
  function sendToParent() {
    dispatch('custom', {
      message: 'Hello from child!',
      timestamp: Date.now()
    });
  }
  
  // 计算属性
  $: uppercaseMessage = message.toUpperCase();
</script>

<div class="child">
  <h2>Child Component</h2>
  
  <!-- 显示 props -->
  <p>Message: {message}</p>
  <p>Uppercase: {uppercaseMessage}</p>
  <p>Count: {count}</p>
  
  <!-- 双向绑定 -->
  <input bind:value placeholder="Bound value" />
  
  <!-- 事件发送 -->
  <button on:click={sendToParent}>Send to Parent</button>
  
  <!-- 插槽定义 -->
  <div class="slots">
    <header>
      <slot name="header">Default Header</slot>
    </header>
    
    <main>
      <slot>Default content</slot>
    </main>
    
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</div>

<style>
  .child {
    margin: 1rem 0;
    padding: 1rem;
    border: 1px solid #28a745;
    border-radius: 0.25rem;
    background: #f8f9fa;
  }
  
  .slots {
    margin-top: 1rem;
    border-top: 1px solid #ddd;
    padding-top: 1rem;
  }
  
  header, footer {
    font-weight: bold;
    color: #007bff;
  }
</style>

高级特性

生命周期和上下文

<!-- Lifecycle.svelte -->
<script>
  import { onMount, onDestroy, beforeUpdate, afterUpdate, tick } from 'svelte';
  import { setContext, getContext } from 'svelte';
  
  // 设置上下文
  setContext('theme', {
    primary: '#007bff',
    secondary: '#6c757d'
  });
  
  let mounted = false;
  let updateCount = 0;
  let data = [];
  
  // 组件挂载后
  onMount(async () => {
    console.log('Component mounted');
    mounted = true;
    
    // 异步数据加载
    try {
      const response = await fetch('/api/data');
      data = await response.json();
    } catch (error) {
      console.error('Failed to load data:', error);
    }
    
    // 返回清理函数
    return () => {
      console.log('Mount cleanup');
    };
  });
  
  // 组件销毁前
  onDestroy(() => {
    console.log('Component destroyed');
  });
  
  // 更新前
  beforeUpdate(() => {
    console.log('Before update');
  });
  
  // 更新后
  afterUpdate(() => {
    console.log('After update');
    updateCount++;
  });
  
  // 异步更新
  async function handleAsyncUpdate() {
    data = [...data, { id: Date.now(), value: Math.random() }];
    
    // 等待 DOM 更新
    await tick();
    
    console.log('DOM updated');
  }
  
  // 定时器示例
  let timer;
  let seconds = 0;
  
  onMount(() => {
    timer = setInterval(() => {
      seconds++;
    }, 1000);
  });
  
  onDestroy(() => {
    if (timer) {
      clearInterval(timer);
    }
  });
</script>

<div class="lifecycle">
  <h2>Lifecycle Demo</h2>
  
  <p>Mounted: {mounted}</p>
  <p>Update count: {updateCount}</p>
  <p>Timer: {seconds}s</p>
  
  <button on:click={handleAsyncUpdate}>
    Add Data (Async)
  </button>
  
  <ul>
    {#each data as item (item.id)}
      <li>{item.id}: {item.value.toFixed(3)}</li>
    {/each}
  </ul>
</div>

<style>
  .lifecycle {
    padding: 1rem;
    border: 1px solid #ddd;
    border-radius: 0.5rem;
  }
  
  ul {
    max-height: 200px;
    overflow-y: auto;
  }
</style>

存储和状态管理

// stores.js
import { writable, readable, derived } from 'svelte/store';

// 可写存储
export const count = writable(0);

// 只读存储
export const time = readable(new Date(), function start(set) {
  const interval = setInterval(() => {
    set(new Date());
  }, 1000);

  return function stop() {
    clearInterval(interval);
  };
});

// 派生存储
export const elapsed = derived(
  time,
  $time => Math.round(($time - start) / 1000)
);

const start = new Date();

// 复杂状态管理
function createUserStore() {
  const { subscribe, set, update } = writable({
    id: null,
    name: '',
    email: '',
    preferences: {
      theme: 'light',
      language: 'en'
    },
    isLoggedIn: false
  });

  return {
    subscribe,
    login: (userData) => update(user => ({
      ...user,
      ...userData,
      isLoggedIn: true
    })),
    logout: () => set({
      id: null,
      name: '',
      email: '',
      preferences: {
        theme: 'light',
        language: 'en'
      },
      isLoggedIn: false
    }),
    updatePreferences: (prefs) => update(user => ({
      ...user,
      preferences: { ...user.preferences, ...prefs }
    })),
    setTheme: (theme) => update(user => ({
      ...user,
      preferences: { ...user.preferences, theme }
    }))
  };
}

export const user = createUserStore();

// 购物车存储
function createCartStore() {
  const { subscribe, set, update } = writable([]);

  return {
    subscribe,
    addItem: (item) => update(cart => {
      const existingItem = cart.find(i => i.id === item.id);
      if (existingItem) {
        return cart.map(i => 
          i.id === item.id 
            ? { ...i, quantity: i.quantity + 1 }
            : i
        );
      }
      return [...cart, { ...item, quantity: 1 }];
    }),
    removeItem: (id) => update(cart => 
      cart.filter(item => item.id !== id)
    ),
    updateQuantity: (id, quantity) => update(cart =>
      quantity <= 0
        ? cart.filter(item => item.id !== id)
        : cart.map(item =>
            item.id === id ? { ...item, quantity } : item
          )
    ),
    clear: () => set([])
  };
}

export const cart = createCartStore();

// 派生的购物车统计
export const cartTotal = derived(cart, $cart =>
  $cart.reduce((total, item) => total + item.price * item.quantity, 0)
);

export const cartItemCount = derived(cart, $cart =>
  $cart.reduce((count, item) => count + item.quantity, 0)
);
<!-- StoreExample.svelte -->
<script>
  import { count, time, user, cart, cartTotal, cartItemCount } from './stores.js';
  
  // 订阅存储(自动前缀 $)
  $: console.log('Count changed:', $count);
  
  function increment() {
    count.update(n => n + 1);
  }
  
  function decrement() {
    count.update(n => n - 1);
  }
  
  function reset() {
    count.set(0);
  }
  
  // 用户操作
  function login() {
    user.login({
      id: 1,
      name: 'John Doe',
      email: 'john@example.com'
    });
  }
  
  function logout() {
    user.logout();
  }
  
  function toggleTheme() {
    user.setTheme($user.preferences.theme === 'light' ? 'dark' : 'light');
  }
  
  // 购物车操作
  const products = [
    { id: 1, name: 'Product A', price: 10.99 },
    { id: 2, name: 'Product B', price: 15.99 },
    { id: 3, name: 'Product C', price: 8.99 }
  ];
  
  function addToCart(product) {
    cart.addItem(product);
  }
</script>

<div class="store-demo" class:dark={$user.preferences.theme === 'dark'}>
  <section>
    <h2>Counter Store</h2>
    <p>Count: {$count}</p>
    <button on:click={increment}>+</button>
    <button on:click={decrement}>-</button>
    <button on:click={reset}>Reset</button>
  </section>
  
  <section>
    <h2>Time Store</h2>
    <p>Current time: {$time.toLocaleTimeString()}</p>
  </section>
  
  <section>
    <h2>User Store</h2>
    {#if $user.isLoggedIn}
      <p>Welcome, {$user.name}!</p>
      <p>Theme: {$user.preferences.theme}</p>
      <button on:click={toggleTheme}>Toggle Theme</button>
      <button on:click={logout}>Logout</button>
    {:else}
      <button on:click={login}>Login</button>
    {/if}
  </section>
  
  <section>
    <h2>Shopping Cart</h2>
    <div class="products">
      {#each products as product}
        <div class="product">
          <span>{product.name} - ${product.price}</span>
          <button on:click={() => addToCart(product)}>Add to Cart</button>
        </div>
      {/each}
    </div>
    
    <div class="cart-summary">
      <p>Items in cart: {$cartItemCount}</p>
      <p>Total: ${$cartTotal.toFixed(2)}</p>
    </div>
    
    {#if $cart.length > 0}
      <div class="cart-items">
        <h3>Cart Items:</h3>
        {#each $cart as item}
          <div class="cart-item">
            <span>{item.name} x {item.quantity}</span>
            <button on:click={() => cart.updateQuantity(item.id, item.quantity + 1)}>+</button>
            <button on:click={() => cart.updateQuantity(item.id, item.quantity - 1)}>-</button>
            <button on:click={() => cart.removeItem(item.id)}>Remove</button>
          </div>
        {/each}
        <button on:click={() => cart.clear()}>Clear Cart</button>
      </div>
    {/if}
  </section>
</div>

<style>
  .store-demo {
    padding: 2rem;
    transition: all 0.3s ease;
  }
  
  .store-demo.dark {
    background: #333;
    color: white;
  }
  
  section {
    margin-bottom: 2rem;
    padding: 1rem;
    border: 1px solid #ddd;
    border-radius: 0.5rem;
  }
  
  .dark section {
    border-color: #555;
    background: #444;
  }
  
  .products, .cart-items {
    margin-top: 1rem;
  }
  
  .product, .cart-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem;
    margin: 0.5rem 0;
    border: 1px solid #eee;
    border-radius: 0.25rem;
  }
  
  .dark .product, .dark .cart-item {
    border-color: #666;
  }
  
  button {
    margin: 0.25rem;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 0.25rem;
    cursor: pointer;
    background: #007bff;
    color: white;
  }
  
  button:hover {
    background: #0056b3;
  }
  
  .cart-summary {
    font-weight: bold;
    margin: 1rem 0;
  }
</style>

SvelteKit 全栈开发

项目结构和路由

// src/app.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%sveltekit.assets%/favicon.png" />
    <meta name="viewport" content="width=device-width" />
    %sveltekit.head%
  </head>
  <body data-sveltekit-preload-data="hover">
    <div style="display: contents">%sveltekit.body%</div>
  </body>
</html>
<!-- src/routes/+layout.svelte -->
<script>
  import '../app.css';
  import { page } from '$app/stores';
  import { navigating } from '$app/stores';
  
  // 全局状态
  import { user } from '$lib/stores/user.js';
  
  $: currentPath = $page.url.pathname;
</script>

<div class="app">
  <header>
    <nav>
      <a href="/" class:active={currentPath === '/'}>Home</a>
      <a href="/about" class:active={currentPath === '/about'}>About</a>
      <a href="/blog" class:active={currentPath.startsWith('/blog')}>Blog</a>
      <a href="/products" class:active={currentPath.startsWith('/products')}>Products</a>
      
      {#if $user.isLoggedIn}
        <a href="/dashboard" class:active={currentPath.startsWith('/dashboard')}>Dashboard</a>
        <button on:click={() => user.logout()}>Logout</button>
      {:else}
        <a href="/login" class:active={currentPath === '/login'}>Login</a>
      {/if}
    </nav>
  </header>
  
  <main>
    {#if $navigating}
      <div class="loading">Loading...</div>
    {/if}
    
    <slot />
  </main>
  
  <footer>
    <p>&copy; 2024 SvelteKit App</p>
  </footer>
</div>

<style>
  .app {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
  }
  
  header {
    background: #007bff;
    color: white;
    padding: 1rem;
  }
  
  nav {
    display: flex;
    gap: 1rem;
    align-items: center;
  }
  
  nav a {
    color: white;
    text-decoration: none;
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
  }
  
  nav a:hover, nav a.active {
    background: rgba(255, 255, 255, 0.2);
  }
  
  main {
    flex: 1;
    padding: 2rem;
  }
  
  .loading {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background: #007bff;
    color: white;
    text-align: center;
    padding: 0.5rem;
    z-index: 1000;
  }
  
  footer {
    background: #f8f9fa;
    text-align: center;
    padding: 1rem;
    border-top: 1px solid #ddd;
  }
</style>

服务器端渲染和 API

// src/routes/+page.server.js
import { error } from '@sveltejs/kit';

export async function load({ fetch, url }) {
  try {
    // 服务器端数据获取
    const response = await fetch('/api/featured-products');
    
    if (!response.ok) {
      throw error(response.status, 'Failed to load featured products');
    }
    
    const featuredProducts = await response.json();
    
    return {
      featuredProducts,
      meta: {
        title: 'Welcome to Our Store',
        description: 'Discover amazing products at great prices'
      }
    };
  } catch (err) {
    throw error(500, 'Server error');
  }
}
<!-- src/routes/+page.svelte -->
<script>
  import { onMount } from 'svelte';
  import ProductCard from '$lib/components/ProductCard.svelte';
  
  export let data;
  
  $: ({ featuredProducts, meta } = data);
  
  let clientOnlyData = [];
  
  onMount(async () => {
    // 客户端数据获取
    const response = await fetch('/api/recommendations');
    clientOnlyData = await response.json();
  });
</script>

<svelte:head>
  <title>{meta.title}</title>
  <meta name="description" content={meta.description} />
</svelte:head>

<div class="home">
  <section class="hero">
    <h1>Welcome to Our Store</h1>
    <p>Discover amazing products at great prices</p>
  </section>
  
  <section class="featured">
    <h2>Featured Products</h2>
    <div class="product-grid">
      {#each featuredProducts as product}
        <ProductCard {product} />
      {/each}
    </div>
  </section>
  
  {#if clientOnlyData.length > 0}
    <section class="recommendations">
      <h2>Recommended for You</h2>
      <div class="product-grid">
        {#each clientOnlyData as product}
          <ProductCard {product} />
        {/each}
      </div>
    </section>
  {/if}
</div>

<style>
  .home {
    max-width: 1200px;
    margin: 0 auto;
  }
  
  .hero {
    text-align: center;
    padding: 4rem 0;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border-radius: 1rem;
    margin-bottom: 3rem;
  }
  
  .hero h1 {
    font-size: 3rem;
    margin-bottom: 1rem;
  }
  
  .product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 2rem;
    margin-top: 2rem;
  }
  
  section {
    margin-bottom: 3rem;
  }
</style>

API 路由

// src/routes/api/products/+server.js
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/database.js';

export async function GET({ url }) {
  try {
    const page = parseInt(url.searchParams.get('page') || '1');
    const limit = parseInt(url.searchParams.get('limit') || '10');
    const category = url.searchParams.get('category');
    const search = url.searchParams.get('search');
    
    const offset = (page - 1) * limit;
    
    let query = 'SELECT * FROM products WHERE 1=1';
    const params = [];
    
    if (category) {
      query += ' AND category = ?';
      params.push(category);
    }
    
    if (search) {
      query += ' AND (name LIKE ? OR description LIKE ?)';
      params.push(`%${search}%`, `%${search}%`);
    }
    
    query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
    params.push(limit, offset);
    
    const products = await db.query(query, params);
    
    // 获取总数
    let countQuery = 'SELECT COUNT(*) as total FROM products WHERE 1=1';
    const countParams = [];
    
    if (category) {
      countQuery += ' AND category = ?';
      countParams.push(category);
    }
    
    if (search) {
      countQuery += ' AND (name LIKE ? OR description LIKE ?)';
      countParams.push(`%${search}%`, `%${search}%`);
    }
    
    const [{ total }] = await db.query(countQuery, countParams);
    
    return json({
      products,
      pagination: {
        page,
        limit,
        total,
        pages: Math.ceil(total / limit)
      }
    });
  } catch (err) {
    console.error('Database error:', err);
    throw error(500, 'Failed to fetch products');
  }
}

export async function POST({ request }) {
  try {
    const product = await request.json();
    
    // 验证数据
    if (!product.name || !product.price) {
      throw error(400, 'Name and price are required');
    }
    
    const result = await db.query(
      'INSERT INTO products (name, description, price, category) VALUES (?, ?, ?, ?)',
      [product.name, product.description, product.price, product.category]
    );
    
    const newProduct = await db.query(
      'SELECT * FROM products WHERE id = ?',
      [result.insertId]
    );
    
    return json(newProduct[0], { status: 201 });
  } catch (err) {
    if (err.status) throw err;
    console.error('Database error:', err);
    throw error(500, 'Failed to create product');
  }
}
// src/routes/api/products/[id]/+server.js
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/database.js';

export async function GET({ params }) {
  try {
    const products = await db.query(
      'SELECT * FROM products WHERE id = ?',
      [params.id]
    );
    
    if (products.length === 0) {
      throw error(404, 'Product not found');
    }
    
    return json(products[0]);
  } catch (err) {
    if (err.status) throw err;
    console.error('Database error:', err);
    throw error(500, 'Failed to fetch product');
  }
}

export async function PUT({ params, request }) {
  try {
    const updates = await request.json();
    
    const result = await db.query(
      'UPDATE products SET name = ?, description = ?, price = ?, category = ? WHERE id = ?',
      [updates.name, updates.description, updates.price, updates.category, params.id]
    );
    
    if (result.affectedRows === 0) {
      throw error(404, 'Product not found');
    }
    
    const updatedProduct = await db.query(
      'SELECT * FROM products WHERE id = ?',
      [params.id]
    );
    
    return json(updatedProduct[0]);
  } catch (err) {
    if (err.status) throw err;
    console.error('Database error:', err);
    throw error(500, 'Failed to update product');
  }
}

export async function DELETE({ params }) {
  try {
    const result = await db.query(
      'DELETE FROM products WHERE id = ?',
      [params.id]
    );
    
    if (result.affectedRows === 0) {
      throw error(404, 'Product not found');
    }
    
    return json({ success: true });
  } catch (err) {
    if (err.status) throw err;
    console.error('Database error:', err);
    throw error(500, 'Failed to delete product');
  }
}

性能优化和最佳实践

代码分割和懒加载

<!-- src/routes/dashboard/+page.svelte -->
<script>
  import { onMount } from 'svelte';
  
  let HeavyComponent;
  let showHeavyComponent = false;
  
  // 懒加载组件
  async function loadHeavyComponent() {
    if (!HeavyComponent) {
      const module = await import('$lib/components/HeavyComponent.svelte');
      HeavyComponent = module.default;
    }
    showHeavyComponent = true;
  }
  
  // 预加载
  onMount(() => {
    // 预加载但不立即显示
    import('$lib/components/HeavyComponent.svelte');
  });
</script>

<div class="dashboard">
  <h1>Dashboard</h1>
  
  <button on:click={loadHeavyComponent}>
    Load Heavy Component
  </button>
  
  {#if showHeavyComponent && HeavyComponent}
    <svelte:component this={HeavyComponent} />
  {/if}
</div>

性能监控

// src/lib/utils/performance.js
export class PerformanceMonitor {
  constructor() {
    this.metrics = new Map();
  }
  
  startTiming(name) {
    this.metrics.set(name, performance.now());
  }
  
  endTiming(name) {
    const start = this.metrics.get(name);
    if (start) {
      const duration = performance.now() - start;
      console.log(`${name}: ${duration.toFixed(2)}ms`);
      this.metrics.delete(name);
      return duration;
    }
  }
  
  measureComponent(component, props = {}) {
    return {
      ...component,
      $$render: (...args) => {
        this.startTiming(`render-${component.name}`);
        const result = component.$$render(...args);
        this.endTiming(`render-${component.name}`);
        return result;
      }
    };
  }
}

export const perfMonitor = new PerformanceMonitor();

总结

Svelte 的核心优势和最佳实践:

🎯 核心优势

  1. 编译时优化:生成高效的原生 JavaScript
  2. 无虚拟 DOM:直接操作 DOM,性能卓越
  3. 简洁语法:学习曲线平缓,开发效率高
  4. 小包体积:编译后的代码体积极小

✅ 适用场景

  • 性能要求高的应用
  • 包体积敏感的项目
  • 快速原型开发
  • 静态网站和 SPA
  • 渐进式 Web 应用

🚀 最佳实践

  • 合理使用响应式声明
  • 利用存储管理全局状态
  • 组件化设计和复用
  • 服务器端渲染优化
  • 代码分割和懒加载

💡 开发建议

  • 充分利用编译时优化
  • 遵循 Svelte 的响应式模式
  • 使用 SvelteKit 构建全栈应用
  • 关注性能和用户体验
  • 保持代码简洁和可维护

掌握 Svelte,体验编译时优化的强大威力!


Svelte 代表了前端框架的新方向,通过编译时优化提供了卓越的性能和开发体验。