Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte #9

Open
jsiwa opened this issue May 22, 2024 · 8 comments
Open

Svelte #9

jsiwa opened this issue May 22, 2024 · 8 comments

Comments

@jsiwa
Copy link
Owner

jsiwa commented May 22, 2024

Svelte 是一种现代化的 JavaScript 框架,用于构建用户界面(UI)。与其他流行的框架(如 React 和 Vue)不同,Svelte 采用了一种独特的方法,通过在构建时(compile-time)而不是在运行时(runtime)处理代码,这使得生成的代码更小、更快,并且更高效。以下是对 Svelte 背景的详细介绍:

背景与历史

  1. 创始人: Svelte 由 Rich Harris 创建,他是一位著名的 JavaScript 开发者,曾经是 The Guardian 的互动新闻开发者。他在 2016 年首次发布了 Svelte,目标是解决现有框架在性能和复杂性上的问题。

  2. 版本演进:

    • Svelte 1(2016年):最初版本,主要证明了概念。
    • Svelte 2(2018年):引入了一些语法改进和功能增强。
    • Svelte 3(2019年):一次重大重构,引入了更直观的语法和强大的编译器功能,使其成为更广泛接受的框架。
  3. 发展方向: Svelte 的发展方向始终是简化开发者的工作,提供更好的性能,并减少应用程序的复杂性和体积。通过在构建时编译组件,Svelte 避免了传统框架在运行时引入的开销。

核心理念

  1. 编译时而非运行时:

    • 编译时处理:Svelte 在构建过程中将组件编译成高效的、优化的 JavaScript 代码。这意味着没有虚拟 DOM 的开销,运行时也没有框架代码的依赖。
    • 性能优势:由于没有虚拟 DOM 的差异对比和更新,Svelte 应用通常具有更好的性能,特别是在处理大量动态更新时。
  2. 简洁直观的语法:

    • 组件结构:Svelte 组件由 HTML、CSS 和 JavaScript 三部分组成,统一在一个文件中,这使得组件的创建和维护更加简单和直观。
    • 反应式声明:通过直接在 JavaScript 中声明变量和使用它们,Svelte 自动跟踪依赖关系,简化了状态管理和反应性处理。
  3. 零样板代码:

    • 减少模板代码:Svelte 的设计理念之一是减少开发者需要编写的模板代码。通过智能编译和自动化的优化,开发者可以专注于业务逻辑和 UI 设计,而不是框架的具体实现。

技术特点

  1. 反应性声明:

    • 自动更新:通过简单的赋值操作(如 count = count + 1),Svelte 能够自动更新 DOM 中的相关部分,而无需显式的状态管理代码。
    • $:语法糖:Svelte 使用 $: 声明反应式语句,当依赖的变量发生变化时,自动重新计算表达式。
  2. 样式作用域:

    • 局部样式:组件内的 CSS 默认是局部作用域,避免了样式污染和冲突。
    • 简化样式管理:通过内联样式和 scoped CSS,Svelte 提供了简洁而强大的样式管理能力。
  3. 高效的事件处理:

    • 事件绑定:Svelte 提供了简单而强大的事件绑定机制,支持原生事件和自定义事件。
    • 简洁的语法:通过 on:click={handleClick} 这样的语法,开发者可以轻松地绑定事件处理函数。

社区与生态系统

  1. 社区支持: Svelte 社区不断壮大,有多个活跃的论坛、聊天室和会议。官方和社区贡献了大量的教程、示例和文档,帮助新手快速上手。
  2. 工具与插件:
    • SvelteKit:一个用于构建 Svelte 应用的全栈框架,提供了服务器端渲染、静态生成、路由和 API 集成等功能。
    • 社区插件:社区开发了丰富的插件和工具,涵盖状态管理、路由、动画、表单处理等多个方面,进一步增强了 Svelte 的功能。

未来发展

Svelte 的未来发展方向主要集中在以下几个方面:

  1. 性能优化:继续提升编译器的效率和生成代码的性能,使得 Svelte 应用在各种场景下都能表现出色。
  2. 工具链完善:改进 SvelteKit 和其他开发工具,为开发者提供更好的开发体验和更强大的功能支持。
  3. 社区扩展:通过社区的力量,丰富生态系统,增加更多的第三方库和插件,满足各种开发需求。
@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

目前,Svelte 的最新版本是 Svelte 4.2.17,这是在几天前发布的。Svelte 4 专注于修复漏洞和改进性能,同时 Svelte 5 已进入预览阶段,并即将发布。Svelte 4 的更新主要包括优化代码生成和提升运行时性能,确保开发者能够更高效地构建现代 web 应用。

Svelte 4 的主要特点

  1. 编译时优化:Svelte 通过在编译时将组件转换为高效的 JavaScript 代码,减少了运行时的开销。这种方法使得应用程序在运行时更快,并且生成的代码更小。

  2. 反应式声明:Svelte 采用简单的反应式声明方式,使得开发者可以轻松地创建动态交互效果。变量的变化会自动触发相应的 DOM 更新,无需额外的状态管理工具。

  3. 样式作用域:每个组件的 CSS 都是作用域化的,避免了全局样式污染。这使得样式管理更加直观和高效。

Svelte 5 预览版的改进

Svelte 5 引入了一些新的特性和改进,包括更简洁的客户端 API 和嵌套 CSS 支持。新的 $inspect$state 特性使开发者能够更方便地调试和管理状态。

  1. $inspect:类似于 console.log,但每当其参数发生变化时会重新运行,方便开发者调试代码。
  2. $state:通过代理机制,使反应性嵌套成为默认行为,简化了复杂状态的管理。

Svelte 社区与生态系统

Svelte 社区活跃,提供了丰富的资源和工具,包括 SvelteKit,这是一个用于构建全栈应用的框架。SvelteKit 提供了服务器端渲染、静态站点生成等功能,使得开发者可以轻松构建高性能的 web 应用。

此外,社区还开发了许多插件和库,进一步扩展了 Svelte 的功能,例如状态管理、路由、动画等,使其适用于各种应用场景。

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

介绍 Svelte 5 中的 Runes

Svelte 5 引入了一个新的核心特性:Runes。Runes 是一种新的反应性 API,旨在提升开发者的开发体验,并提供更强大的状态管理和事件处理功能。以下是对 Runes 详细介绍。

什么是 Runes

Runes 是 Svelte 5 中用于处理反应性数据和状态的新机制。它们通过引入更细粒度的信号和反应性,简化了复杂应用的状态管理和数据流控制。与传统的反应性系统相比,Runes 提供了更灵活和强大的功能。

主要特性

  1. $effect Rune:

    • $effect 是 Runes 中最基础的构造块,用于在特定条件下执行副作用。它类似于 useEffect,但语法更加简洁。
    • 示例:
      <script>
        $effect(() => {
          console.log('This will run when the component is mounted');
        });
      </script>
  2. $state Rune:

    • $state 用于创建具有反应性的状态,并且状态变化时会自动触发相关的副作用。
    • 示例:
      <script>
        let count = $state(0);
      
        $effect(() => {
          console.log(`Count is now ${count}`);
        });
      </script>
  3. $inspect Rune:

    • $inspect 类似于 console.log,但每当其参数发生变化时会重新运行,方便调试。
    • 示例:
      <script>
        let name = $state('John');
      
        $inspect(name);
      </script>
  4. 嵌套反应性:

    • $state 可以嵌套使用,使得处理复杂的嵌套数据结构变得更加简单和直观。
    • 示例:
      <script>
        let user = $state({ name: 'John', age: 30 });
      
        $effect(() => {
          console.log(`User's name is ${user.name}`);
        });
      </script>
  5. $effect.pre 和 $effect.root:

    • $effect.pre 用于在更新前执行副作用,而 $effect.root 则用于在根级别管理反应性。
    • 示例:
      <script>
        let value = $state(10);
      
        $effect.pre(() => {
          console.log('This runs before the DOM update');
        });
      
        $effect.root(() => {
          console.log('This runs at the root level');
        });
      </script>

优点

  1. 简化反应性管理: Runes 提供了更简洁和直观的方式来处理组件中的反应性和副作用,使代码更易读易维护。
  2. 提升性能: 通过更细粒度的信号管理,Runes 可以减少不必要的重新渲染和性能开销。
  3. 增强灵活性: 开发者可以根据需要在组件级别或全局级别使用 Runes,使其适应不同的开发需求。

使用 Runes

要在 Svelte 5 项目中启用 Runes,可以在组件文件中添加 runes 选项,或在项目的配置文件中全局启用:

<svelte:options runes={true} />

或者在 svelte.config.js 中:

export default {
  compilerOptions: {
    runes: true
  }
};

结论

Runes 是 Svelte 5 中的一项重要改进,通过简化反应性管理和提供更强大的功能,显著提升了开发体验。开发者可以通过使用 Runes 构建更高效、可维护的现代 Web 应用。

更多详细信息可以访问 Svelte 官方博客Svelte 文档

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

Svelte 5 的发布预计将在 2024 年内完成,目前已经处于发布候选阶段。这个版本的设计已经基本确定,主要集中在性能改进和开发者体验的提升。Svelte 5 引入了 Runes API,这是一种基于信号的反应性 API,提供更细粒度和通用的反应性处理能力【81†source】【82†source】。

浏览器兼容性

Svelte 4 和即将推出的 Svelte 5 主要支持现代浏览器,以下是详细的兼容性信息:

  1. Svelte 的核心库

    • 支持所有现代浏览器,包括 Chrome、Firefox、Safari 和 Edge 等。
    • 对于不支持某些现代特性的较旧浏览器,可以通过使用 Babel 和 Polyfill 进行适配。Svelte 的官方文档和社区资源提供了相关的指导。
  2. SvelteKit 的要求

    • SvelteKit 2 版本要求使用 ES2022 特性,因此需要在支持这些特性的浏览器中运行。支持的浏览器版本包括:
      • Chrome 94+
      • Edge 94+
      • Firefox 93+
      • Safari 16.4+
      • Samsung Internet 17.0+

这些浏览器版本在 2021 年至 2023 年间发布,涵盖了所有主要的现代浏览器和设备【82†source】【83†source】。

兼容性保障

为了确保兼容性,开发者可以采取以下措施:

  1. 使用 Polyfill:对于不支持的特性,可以使用 Polyfill,例如 core-js,来添加必要的功能支持。
  2. Babel 转码:使用 Babel 将现代 JavaScript 代码转码为旧版本的 JavaScript,以支持较旧的浏览器。
  3. 兼容性测试:在开发过程中,定期在目标浏览器中进行测试,确保应用能够在所有支持的浏览器中正常运行。

总结

Svelte 旨在支持所有现代浏览器,并通过编译时优化和高效的运行时性能,提供卓越的用户体验。对于较旧的浏览器,开发者可以通过使用 Babel 和 Polyfill 等工具来确保兼容性。如果你正在考虑将 Svelte 应用于商业项目,可以放心其对现代浏览器的广泛支持。

更多详细信息和更新,请访问 Svelte 官方博客GitHub

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

Svelte 支持 WebSocket 主要通过 SvelteKit 实现。SvelteKit 是 Svelte 的全栈框架,能够在开发和生产环境中使用 WebSocket。以下是一些详细信息和实现方法:

在 SvelteKit 中使用 WebSocket

开发环境中的 WebSocket

在开发环境中,可以使用 Vite 的 configureServer 方法来集成 WebSocket 服务器。例如,可以使用 socket.io 库来实现 WebSocket 连接:

// vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import { Server } from 'socket.io';

const webSocketServer = {
  name: 'webSocketServer',
  configureServer(server) {
    if (!server.httpServer) return;

    const io = new Server(server.httpServer);
    io.on('connection', (socket) => {
      socket.emit('eventFromServer', 'Hello, World');
    });
  }
};

export default defineConfig({
  plugins: [sveltekit(), webSocketServer]
});

在客户端,使用 socket.io-client 进行连接和消息处理:

<script lang="ts">
  import { io } from 'socket.io-client';

  const socket = io();

  socket.on('eventFromServer', (message) => {
    console.log(message);
  });
</script>

生产环境中的 WebSocket

在生产环境中,可以使用 Express 和 socket.io 结合 SvelteKit 来创建 WebSocket 服务器。以下是一个简单的实现示例:

// server.js
import http from 'http';
import express from 'express';
import { Server } from 'socket.io';
import { handler } from '../build/handler.js';

const app = express();
const server = http.createServer(app);
const io = new Server(server);

io.on('connection', (socket) => {
  socket.emit('eventFromServer', 'Hello, World');
});

app.use(handler);

server.listen(3000, () => {
  console.log('Running on http://localhost:3000');
});

在客户端,同样使用 socket.io-client 来处理 WebSocket 连接:

<script lang="ts">
  import { io } from '$lib/webSocketConnection.js';
  import { onMount } from 'svelte';

  let messages = [];

  onMount(() => {
    io.on('message', (message) => {
      messages = [...messages, message];
    });
  });

  function sendMessage() {
    const message = textfield.trim();
    if (!message) return;

    textfield = '';
    io.emit('message', message);
  }
</script>

<div>
  {#each messages as message}
    <div>{message}</div>
  {/each}
  <input bind:value={textfield} placeholder="Type something..." />
  <button on:click={sendMessage}>Send</button>
</div>

小结

通过 SvelteKit 的集成,Svelte 应用可以轻松地实现 WebSocket 功能。无论是在开发环境还是生产环境,都可以通过配置 Vite 或使用 Express 和 socket.io 来实现实时通信功能。这使得 Svelte 应用在处理实时数据和事件驱动的应用时变得更加灵活和高效。

更多详细信息和代码示例可以参考以下资源:

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

Svelte 源码的一些关键部分的解析,帮助理解其内部工作机制。

1. 编译器架构

Svelte 的核心是其编译器,它将 Svelte 组件代码转换为高效的 JavaScript。编译器的主要功能模块包括解析、转换和代码生成。

解析阶段

解析阶段将 .svelte 文件转换为抽象语法树(AST)。这一阶段主要使用 acorn 库来解析 JavaScript,并使用 svelte-parser 来解析模板和样式。

import { parse } from 'svelte/compiler';
const ast = parse(source);

转换阶段

在转换阶段,编译器对 AST 进行各种优化和转换,包括:

  • 将模板指令(如 {#if}{#each})转换为对应的 JavaScript 代码。
  • 处理反应性声明(如 $:)。
  • 处理组件间通信(如 propsevents)。

代码生成阶段

代码生成阶段将优化后的 AST 转换为可执行的 JavaScript 代码,这包括:

  • 生成组件的初始化代码。
  • 生成更新和销毁组件的代码。
  • 处理样式的作用域化。
import { compile } from 'svelte/compiler';
const { js, css } = compile(source);

2. 反应性系统

Svelte 的反应性系统通过编译时分析实现。开发者在代码中使用普通的赋值操作,编译器会在编译时检测这些操作并生成相应的更新逻辑。

反应性声明

反应性声明使用 $: 前缀。例如,以下代码会在 count 变化时自动更新 doubled 的值:

let count = 0;
$: doubled = count * 2;

编译后的代码大致如下:

let count = 0;
let doubled;
function update() {
  doubled = count * 2;
}
update();

3. 组件系统

Svelte 的组件系统通过编译器生成的类来实现。每个组件被编译为一个类,这个类包含初始化、更新和销毁的逻辑。

组件初始化

在组件初始化时,编译器生成的类会创建 DOM 元素,并将它们附加到页面上。以下是一个简化的组件初始化示例:

class MyComponent {
  constructor(options) {
    this.init(options);
  }

  init({ target, props }) {
    this.target = target;
    this.props = props;
    this.render();
  }

  render() {
    this.target.innerHTML = `<h1>${this.props.title}</h1>`;
  }
}

new MyComponent({ target: document.body, props: { title: 'Hello, world!' } });

更新和销毁

更新和销毁的逻辑也是在编译时生成的。每个组件都会有一个更新函数,用于在状态改变时更新 DOM,以及一个销毁函数,用于清理组件实例。

4. 样式作用域化

Svelte 在编译时对组件的样式进行作用域化处理,避免样式冲突。每个组件的样式会被编译为一个唯一的选择器前缀。

样式作用域化示例

例如,以下样式:

h1 {
  color: red;
}

会被编译为:

h1.svelte-1abcd12 {
  color: red;
}

相应的,组件模板中的元素也会添加相应的类名:

<h1 class="svelte-1abcd12">Hello, world!</h1>

结论

Svelte 通过编译时优化,将开发者编写的代码转换为高效的 JavaScript,使得生成的应用具有更好的性能和更小的体积。其核心包括编译器架构、反应性系统、组件系统和样式作用域化等部分。这些特性使得 Svelte 在现代前端开发中具有显著优势。

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

1. 编译器架构

Svelte 的编译器由多个模块组成,主要包括 parsetransformgenerate

解析阶段(parse)

parse 模块负责将 Svelte 组件的源代码解析成抽象语法树(AST)。它使用 acorn 库解析 JavaScript 部分,并使用自定义的解析器解析模板和样式。

// src/compiler/parse/index.ts
import { parse } from 'acorn';
import { parseTemplate } from './template';

export function parse(source) {
  const jsAst = parse(source.script.content, { ecmaVersion: 2020 });
  const templateAst = parseTemplate(source.template.content);
  
  return {
    jsAst,
    templateAst,
    styles: source.styles
  };
}

转换阶段(transform)

transform 模块负责对 AST 进行各种优化和转换,包括处理反应性声明和模板指令。

// src/compiler/transform/index.ts
import { transformReactiveDeclarations } from './reactive';
import { transformTemplate } from './template';

export function transform(ast) {
  transformReactiveDeclarations(ast.jsAst);
  transformTemplate(ast.templateAst);
  
  return ast;
}

代码生成阶段(generate)

generate 模块负责将优化后的 AST 转换为 JavaScript 代码。它生成组件的初始化、更新和销毁逻辑。

// src/compiler/generate/index.ts
import { generateComponent } from './component';

export function generate(ast) {
  const componentCode = generateComponent(ast);
  
  return {
    js: componentCode.js,
    css: componentCode.css
  };
}

2. 反应性系统

Svelte 的反应性系统通过编译时分析实现。在编译阶段,Svelte 会检测反应性声明,并生成相应的更新逻辑。

反应性声明的处理

transformReactiveDeclarations 函数中,编译器会识别以 $: 开头的语句,并将其转换为包含依赖关系的更新函数。

// src/compiler/transform/reactive.ts
export function transformReactiveDeclarations(jsAst) {
  jsAst.body.forEach(node => {
    if (node.type === 'ExpressionStatement' && node.expression.type === 'AssignmentExpression') {
      const { left, right } = node.expression;
      if (left.type === 'Identifier' && left.name.startsWith('$')) {
        // 转换反应性声明
        const dependency = left.name.slice(1);
        node.expression.right = generateUpdateFunction(dependency, right);
      }
    }
  });
}

function generateUpdateFunction(dependency, expression) {
  return {
    type: 'FunctionExpression',
    params: [],
    body: {
      type: 'BlockStatement',
      body: [{
        type: 'ExpressionStatement',
        expression
      }]
    }
  };
}

3. 组件系统

Svelte 的组件系统通过编译器生成的类来实现。每个组件被编译为一个类,这个类包含初始化、更新和销毁的逻辑。

组件初始化

在组件初始化时,编译器生成的类会创建 DOM 元素,并将它们附加到页面上。

// src/compiler/generate/component.ts
export function generateComponent(ast) {
  const { jsAst, templateAst } = ast;
  
  const initCode = generateInitCode(templateAst);
  const updateCode = generateUpdateCode(jsAst);
  
  return {
    js: `
      class Component {
        constructor(options) {
          this.init(options);
        }

        init({ target, props }) {
          ${initCode}
        }

        update() {
          ${updateCode}
        }
      }

      export default Component;
    `,
    css: generateCss(ast.styles)
  };
}

function generateInitCode(templateAst) {
  // 生成初始化代码
}

function generateUpdateCode(jsAst) {
  // 生成更新代码
}

function generateCss(styles) {
  // 生成样式代码
}

4. 样式作用域化

Svelte 在编译时对组件的样式进行作用域化处理,避免样式冲突。每个组件的样式会被编译为一个唯一的选择器前缀。

样式作用域化示例

在解析和生成 CSS 的过程中,Svelte 会添加唯一的选择器前缀,确保样式作用域化。

// src/compiler/parse/style.ts
export function parseStyles(styles) {
  return styles.map(style => {
    const scopedCss = scopeCss(style.content, generateScopedClassName());
    return {
      ...style,
      content: scopedCss
    };
  });
}

function scopeCss(css, scope) {
  // 添加选择器前缀
}

function generateScopedClassName() {
  return `svelte-${Math.random().toString(36).substr(2, 9)}`;
}

@jsiwa
Copy link
Owner Author

jsiwa commented May 22, 2024

Bun 对 Svelte 的支持主要通过 svelte-adapter-bun 实现,这是一个 SvelteKit 的适配器,可以生成独立的 Bun 服务器。以下是如何在 SvelteKit 项目中使用 Bun 的详细步骤:

安装和配置

  1. 创建 SvelteKit 项目
    首先,创建一个新的 SvelteKit 项目。如果尚未创建,可以使用以下命令:

    npm create svelte@latest
    cd my-svelte-app
  2. 安装 Bun 和 SvelteKit 适配器
    通过 Bun 包管理器安装 svelte-adapter-bun

    bun add -d svelte-adapter-bun
  3. 配置 SvelteKit
    svelte.config.js 文件中配置适配器:

    // svelte.config.js
    import adapter from "svelte-adapter-bun";
    import { vitePreprocess } from "@sveltejs/kit/vite";
    
    export default {
      kit: {
        adapter: adapter(),
      },
      preprocess: vitePreprocess(),
    };

构建和运行

  1. 构建项目
    使用 Vite 构建生产包:

    bun run build
  2. 启动服务器
    构建完成后,进入构建目录并使用 Bun 启动服务器:

    cd build
    bun run start

配置选项

svelte-adapter-bun 提供了多种配置选项,可以在 svelte.config.js 中进行设置:

  • out:构建输出目录,默认为 build
  • assets:启用静态资源浏览,默认为 true
  • precompress:启用 gzip 和 brotli 压缩,默认关闭。
  • envPrefix:环境变量前缀,可以用来避免变量冲突。
  • development:启用 Bun 的错误页面,默认关闭。
  • dynamic_origin:启用动态 origin,使用 PROTOCOL_HEADERHOST_HEADER,默认为 false

WebSocket 支持

Bun 还支持 WebSocket,可以在 src/hooks.server.js 中配置 WebSocket 处理程序:

// src/hooks.server.js
/** @type {import("svelte-adapter-bun").WebSocketHandler} */
export const handleWebsocket = {
  open(ws) {
    console.log("WebSocket opened");
    ws.send("Welcome to the WebSocket server!");
  },
  upgrade(request, upgrade) {
    const url = new URL(request.url);
    if (url.pathname.startsWith("/ws")) {
      return upgrade(request);
    }
  },
};

总结

通过使用 svelte-adapter-bun,可以轻松地将 SvelteKit 项目与 Bun 结合,利用 Bun 的高性能和快速启动时间来构建和部署现代 Web 应用。更多详细信息可以参考 svelte-adapter-bun 的 GitHub 仓库Bun 的官方文档【115†source】【116†source】【117†source】。

@jsiwa
Copy link
Owner Author

jsiwa commented May 23, 2024

Svelte 有许多知名的 UI 库和组件,可以帮助开发者快速构建用户界面。以下是一些比较知名的 Svelte UI 库:

  1. Svelte Material UI (SMUI): 基于 Material Design 规范的 UI 组件库,提供了丰富的组件集成。

  2. SvelteStrap: 基于 Bootstrap 的 Svelte 组件库,提供了与 Bootstrap 类似的 UI 组件。

  3. SvelteKit: Svelte 官方推出的全栈框架,虽然不是专门的 UI 库,但它提供了强大的开发体验,可以与任何 UI 库集成。

  4. Sveltesian: 轻量级的 Svelte UI 库,提供了一些基础的 UI 组件。

  5. Carbon Components Svelte: IBM Carbon Design System 的 Svelte 实现,适合企业级应用开发。

  6. Svelte UI: 由体积小、性能高著称,提供了一些常见的 UI 组件。

  7. Skeleton: 新兴的 Svelte UI 库,提供现代化的设计和组件。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant