用 Svelte 5 构建桌面应用:Electrobun Svelte 模板的 HMR 开发实战指南
用 Svelte 5 构建桌面应用Electrobun Svelte 模板的 HMR 开发实战指南【免费下载链接】electrobunBuild ultra fast, tiny, and cross-platform desktop apps with Typescript.项目地址: https://gitcode.com/GitHub_Trending/el/electrobunElectrobun 官方提供的 Svelte 模板templates/svelte/将 Svelte 5 的响应式 runes 语法与 Vite 的热模块替换HMR能力引入桌面应用开发流程让开发者获得改代码即时生效、不丢失组件状态的前端开发体验。本文以该模板为核心完整讲解其命令体系、HMR 原理、项目结构与配置文件并结合仓库源码说明每一步的底层机制帮助你快速上手并定制属于自己的 Svelte 桌面应用。模板定位Svelte 5 Vite HMR 的桌面应用起点Electrobun 是一个用 TypeScript 构建跨平台桌面应用的框架它使用 Bun 作为运行时、Cottontail 作为主进程main process并通过views://协议加载打包后的前端资源。templates/svelte/README.md所描述的 Svelte 模板是官方为偏好 Svelte 生态的开发者准备的起步工程其核心特点有三Svelte 5使用全新的 runes 响应式语法$state()、$derived()、$effect()Vite 开发服务器提供 HMR组件改动即时热更新无需整页刷新hutch 命令封装安装依赖、开发、构建全部通过统一的hutch run命令完成。从 templates/svelte/package.json 可以看到模板的依赖构成svelte^5.14.1、vite^6.0.3、sveltejs/vite-plugin-svelte^5.0.1以及用于同时运行两个进程的concurrently^9.1.0。types/bun为 Bun 环境提供类型支持说明主进程代码运行在 Bun 之上。快速开始四条命令掌握完整开发流程模板在 templates/svelte/hutch.config.ts 中定义了全部脚本README 推荐的核心命令如下# 安装依赖使用冻结 lockfile保证依赖可复现 hutch run install # 开发模式无 HMR使用打包后的静态资源 hutch run dev # 开发模式带 HMR推荐日常使用 hutch run dev:hmr # 构建生产版本canary 通道 hutch run build:canary命令底层拆解hutch run会把脚本委托给 hutch 执行。对照 hutch.config.ts 的scripts字段这些命令的真实构成是hutch run命令实际执行内容用途installhutch install --frozen-lockfile按hutch.lock冻结版本安装依赖devhutch electrobun prepare hutch pm exec -- vite build hutch electrobun dev --watch先构建 Vite 产物再以 watch 模式启动 Electrobun加载打包资源dev:hmrhutch pm exec -- concurrently hutch run hmr hutch run start并行启动 Vite 开发服务器与 Electrobun 主进程hmrhutch electrobun prepare hutch pm exec -- vite --port 5173仅启动 5173 端口的 Vite 开发服务器starthutch electrobun prepare hutch pm exec -- vite build hutch electrobun dev构建后启动 Electrobun供dev:hmr调用build... vite build hutch electrobun build --envstable构建 stable 通道版本build:canary... vite build hutch electrobun build --envcanary构建 canary 通道版本注意dev:hmr并非只启动一个进程而是通过concurrently同时拉起两条链路hmrVite 服务器与startElectrobun 应用。这正是 HMR 能够工作的进程级前提。HMR 的工作原理源码级解析README 用四步概括了hutch run dev:hmr的流程Vite 开发服务器在http://localhost:5173启动并开启 HMRElectrobun 启动并检测到正在运行的 Vite 服务器应用从 Vite 开发服务器加载页面而不是加载打包资源Svelte 组件的修改即时生效无需整页刷新。而hutch run dev无 HMR则是Electrobun 直接加载views://mainview/index.htmlVite 在启动前先完成打包。主进程如何探测开发服务器第 2 步检测 Vite 服务器的实现位于主进程入口 templates/svelte/src/bun/index.ts。关键逻辑如下const DEV_SERVER_PORT 5173; const DEV_SERVER_URL http://localhost:${DEV_SERVER_PORT}; // Check if Vite dev server is running for HMR async function getMainViewUrl(): Promisestring { const channel await Updater.localInfo.channel(); if (channel dev) { try { await fetch(DEV_SERVER_URL, { method: HEAD }); console.log(HMR enabled: Using Vite dev server at ${DEV_SERVER_URL}); return DEV_SERVER_URL; } catch { console.log( Vite dev server not running. Run hutch run dev:hmr for HMR support., ); } } return views://mainview/index.html; }这段代码揭示了两个关键设计通道channel判定先通过Updater.localInfo.channel()判断当前运行通道是否为dev。只有开发通道才尝试连接开发服务器生产/预览通道直接回退到打包资源避免意外加载本机 5173 端口HEAD 请求探测向http://localhost:5173发送HEAD请求成功则认定 Vite 已就绪将窗口 URL 指向开发服务器失败则打印提示并回退到views://mainview/index.html。随后 src/bun/index.ts 用探测结果创建窗口const mainWindow new BrowserWindow({ title: Svelte App, url, frame: { width: 900, height: 700, x: 200, y: 200, }, });BrowserWindow与Updater均来自electrobun/main模块这正是模板主进程Cottontail的标准导入方式见 templates/svelte/llms.txt 中的导入说明。Vite 配置如何配合 HMRtemplates/svelte/vite.config.ts 是 HMR 生效的另一半export default defineConfig({ plugins: [svelte()], resolve: { alias: electrobunViteAliases(resolve(__dirname, .hutch/devkit)), }, root: src/mainview, build: { outDir: ../../dist, emptyOutDir: true, }, server: { port: 5173, strictPort: true, }, });要点解析root: src/mainviewVite 以src/mainview/为根目录index.html、main.ts、App.svelte都位于此server.port: 5173strictPort: true固定端口 5173 且不允许端口被占用后自动切换——这与主进程中硬编码的DEV_SERVER_PORT 5173严格对应若端口漂移则探测逻辑会失败build.outDir: ../../dist打包输出到模板根目录下的dist/供后续copy步骤使用electrobunViteAliases来自.hutch/devkithutch 安装时生成的开发工具包为electrobun/view等浏览器端导入提供别名解析。项目结构每个文件都在干什么README 给出了模板目录树结合源码可进一步明确每个文件的职责templates/svelte/ ├── src/ │ ├── bun/ │ │ └── index.ts # 主进程入口Cottontail探测 HMR、创建 BrowserWindow │ └── mainview/ │ ├── App.svelte # Svelte 根组件含 runes 示例 │ ├── main.ts # Svelte 挂载入口mount(App, target) │ ├── index.html # HTML 模板div idapp /main.ts 模块脚本 │ └── app.css # 全局样式盒模型、字体、#app 布局 ├── electrobun.config.ts # Electrobun 应用元数据与构建配置 ├── vite.config.ts # Vite/Svelte 插件、别名、端口与产物目录 ├── svelte.config.js # Svelte 预处理器vitePreprocess ├── hutch.config.ts # hutch 脚本编排install/dev/dev:hmr/build ├── hutch.lock # 依赖冻结清单配合 --frozen-lockfile ├── llms.txt # 面向 LLM 的项目速查Electrobun 非 Electron ├── package.json # 依赖与项目元信息 └── tsconfig.json # 继承 .hutch/devkit 的严格 TS 配置渲染链路为index.html→ 加载/main.ts→main.ts中import ./app.css并mount(App, { target: document.getElementById(app)! })Svelte 5 通过mountAPI 将根组件挂载到#app节点src/mainview/main.ts。而浏览器端Electroview与主进程之间的通信导入统一走electrobun/view模板的 llms.txt 明确提醒Electrobun 不是 Electron不要使用 Electron 的 API 或模式。Svelte 5 runes模板内置的响应式示例模板使用 Svelte 5 的 runes 语法无需on:指令与$:赋值而是编译器级别的响应式原语README 列出的三个核心 runes 在 src/mainview/App.svelte 中均有体现script langts let count $state(0); function increment() { count 1; } function reset() { count 0; } /script$state()声明响应式状态let count $state(0)等价于传统写法中的let count 0 自动追踪依赖。直接赋值count 1即可触发更新$derived()由其他状态推导的计算值模板虽未直接使用但它是 runes 体系的核心——任何对$state的依赖变更都会自动重算$effect()响应式副作用适合在状态变化时执行 DOM 外的逻辑。事件绑定同样使用新语法onclick{increment}代替旧的on:click。模板内的计数器示例在 HMR 场景下尤其有代表性——修改App.svelte保存后Vite 会热替换该组件模块而不重置count状态这正是 README 强调changes instantly without losing state即时更新且不丢状态的实际含义。main.ts使用 Svelte 5 的mountAPI而非 Svelte 4 的new App({ target })挂载应用这也是迁移到 Svelte 5 后推荐的挂载方式。配置深潜Electrobun 构建管线如何消费 Vite 产物templates/svelte/electrobun.config.ts 是应用与框架之间的契约它说明了Vite 打包结果如何变成桌面应用资源import type { ElectrobunConfig } from electrobun; export default { app: { name: svelte-app, identifier: svelteapp.electrobun.dev, version: 0.0.1, }, build: { mainProcess: cottontail, cottontail: { entrypoint: src/bun/index.ts, }, // Vite builds to dist/, we copy from there copy: { dist/index.html: views/mainview/index.html, dist/assets: views/mainview/assets, }, // Ignore Vite output in watch mode — HMR handles view rebuilds separately watchIgnore: [dist/**], mac: { bundleCEF: false }, linux: { bundleCEF: false }, win: { bundleCEF: false }, }, } satisfies ElectrobunConfig;逐项说明app应用名称、反向域名形式的唯一标识符svelteapp.electrobun.dev与版本号mainProcess: cottontailentrypoint指定主进程为 Cottontail入口为src/bun/index.tscopy把 Vite 输出的dist/index.html与dist/assets/复制为views://mainview/...协议下的资源这是无 HMR 模式下views://mainview/index.html得以加载的来源watchIgnore: [dist/**]watch 模式下忽略dist目录——视图层的重建完全交给 Vite/HMR避免双重建与文件抖动bundleCEF: falsemac/linux/win 三个平台均不内嵌 CEF模板面向开发与快速分发场景减小包体积。tsconfig 同样指向 hutch 生成的工具链templates/svelte/tsconfig.json 继承.hutch/devkit/tsconfig.json并开启strict、noUnusedLocals、noUnusedParameters、moduleResolution: bundler等严格选项保证与 Bun Vite 的模块解析方式兼容。定制你的应用五个可改动的入口README 的 Customizing 章节给出了五个定制方向结合源码补充具体改法定制项修改位置说明Svelte 组件src/mainview/ 下的.svelte文件组件结构、交互逻辑、样式style块全局样式src/mainview/app.css默认重置* { box-sizing: border-box }、字体栈与#app布局可扩展为 CSS 变量/设计令牌Vite 设置vite.config.ts新增插件、别名、server端口等若改端口需同步修改 src/bun/index.ts 中的DEV_SERVER_PORT窗口设置src/bun/index.tsBrowserWindow的title、frame宽高、位置可继续添加事件监听或引入其他electrobun/mainAPI应用元数据electrobun.config.tsname、identifier、version以及build.copy等构建规则一个务实的坑位提醒HMR 探测依赖三个位置的端口一致vite.config.ts的server.port、src/bun/index.ts的DEV_SERVER_PORT、以及hutch.config.ts中hmr脚本的vite --port 5173。若修改其中一处而不同步其他两处Electrobun 将探测不到开发服务器静默回退到views://mainview/index.html此时控制台会打印 Vite dev server not running 提示。小结从模板到产品的下一步Electrobun Svelte 模板为Svelte 5 前端 Electrobun 桌面壳提供了一条开箱即用的路径日常开发使用hutch run dev:hmr获得组件级热更新需要复现打包产物行为时使用hutch run dev发布时使用hutch run buildstable或hutch run build:canarycanary 通道理解 src/bun/index.ts 的通道判定与端口探测逻辑是排查 HMR 失效类问题的钥匙。仓库中还有更多变体模板可供参考如 templates/react-tailwind-vite/、templates/vue/、templates/vanilla-vite/ 使用同一套 Vite 多进程机制而 templates/wgpu/ 与 templates/zig-wgpu/ 则展示了 WebGPU 在 Electrobun 中的集成方式。以本文为基础你可以将任意 Svelte 5 应用平滑迁移到 Electrobun 桌面运行时中。【免费下载链接】electrobunBuild ultra fast, tiny, and cross-platform desktop apps with Typescript.项目地址: https://gitcode.com/GitHub_Trending/el/electrobun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考