Wails + SvelteKit 构建桌面应用

作为一名web后端CRUD boy,我一直希望开发一个自己的桌面app。
但是当我稍微了解了一下之后,🫠发现这并不是一件容易的事情。但是转念一想,🤔反正我也不打算写一个特别复杂的应用,直接选择web相关技术来做就好,门槛较低、自己也稍微熟悉一点。

由于我不会nodejs和rust,只对go比较熟悉,所以选择了Wails作为桌面开发框架🥳。前端框架也希望简单因此选择了SvelteKit。至于UI,我发现Svelte相关的UI库相对较少,而且文档也不是很友好(我的英语也不好😢)。看了一圈之后最后决定还是用bootstrap吧,它看起来比较简单直接。

项目搭建步骤

  1. 首先安装wails以及相关工具,这一步官网已经有详细的介绍,参考官网教程
  2. 安装好相关工具以后,使用wails初始化一个项目wails init -n otool -t svelte,这里指定项目名称otool以及项目模板使用svelte。命令执行完毕,就会在当前目录下创建一个名为otool的项目
  3. 接着重新初始化前端模块。进入otool目录,可以发现自带的前端模块目录frontend。我们使用SvelteKit这个web框架,因此自带的不需要,直接删除frontend目录。然后执行npm create svelte@latest frontend创建一个SveleteKit项目的frontend目录。执行该命令后,将询问你一系列问题:
  • 首先是选择创建应用的类型,我们选择Skeleton project来生成一个基本的应用骨架
  • 接着会询问你是否需要 TypeScript 类型检查等问题,我选择的是第一个:使用JavaScript with JSDoc comments
  • 最后选择一些附加选项,按需选择即可
  1. 初始化前端模块以后,还需要更改前端的配置。首先需要修改SvelteKit适配器,该配置用于将Svelte应用程序部署到不同的服务器环境中。默认的适配器是adapter-auto,由于是桌面应用开发为纯静态页面,因此更改适配器为adapter-static。

    进入frontend目录,修改package.json中的devDependencies下的”@sveltejs/adapter-auto” 为”@sveltejs/adapter-static”(静态站点适配器)。修改 svelte.config.js 中的‘@sveltejs/adapter-auto’ 为‘@sveltejs/adapter-static’

  2. 回到otool目录然后执行wails dev,该命令会自动安装相关依赖并在开发模式下运行应用。第一次执行会报错all routes must be fully prerenderable, but found the following routes that are dynamic,在adapter-static模式下,需要我们告诉SvelteKit需要渲染哪些路由,因此会出现这个错误。一般我们是加载所有符合路由规则的文件,所以在frontend/src/routes目录下创建+layout.js文件并写入export const prerender = true;。再次运行wails dev就可以看到弹出的应用窗口了,窗口中会显示Welcome to SvelteKit

  3. 调试模式下没问题后,我们执行wails build看下编译后的app效果。此时会发现编译的app无法正常运行,因为SvelteKit编译后的文件是在frontend/build目录下,因此打开main.go修改嵌入的前端资源路径。将//go:embed all:frontend/dist修改为//go:embed all:frontend/build。再次编译就可以正常打开app了

以上基本工作就做好了,可以开始开发我们的应用

应用布局

我们使用bootstrap来作为ui库,在frontend目录下运行npm install bootstrap@5.3.0-alpha1安装bootstrap。为了适配bootstrap需要再次在frontend/src/routes/+layout.js文件中写入export const ssr = false;通过关闭服务端渲染来避免document is not defined此类浏览器端api在服务端运行时下的错误。

然后创建布局文件frontend/src/routes/+layout.svelte,放入如下代码:

<script>
    import 'bootstrap/dist/css/bootstrap.min.css'
    import 'bootstrap/dist/js/bootstrap.bundle.min.js'
    import Menu from './Menu.svelte'
</script>

<div class="main d-flex flex-row">
    <Menu />
    <div class="flex-fill overflow-scroll">
        <slot></slot>
    </div>
</div>

<style>
    .main {
        height: 100vh;
        width: 100vw;
        overflow-x: auto;
        overflow-y: hidden;
    }
</style>

同目录下创建Menu.svelte,代码如下:

<script>
    let activeItem = null;
    let menus = [
        { name: "menu1", url: "/hello" },
    ];

    function setActive(index) {
        activeItem = index;
    }
</script>

<div class="flex-shrink-0 text-bg-dark p-2 overflow-scroll w-25" style="max-width: 220px;">
    <a
        href="/"
        on:click={() => setActive(-1)}
        class="d-flex justify-content-center text-white text-decoration-none"
    >
        <span class="fs-4">oapp</span>
    </a>
    <hr />
    <ul class="nav nav-pills flex-column mb-auto">
        {#each menus as item, index}
            <li class="nav-item">
                <a
                    href={item.url}
                    class="nav-link text-white d-flex justify-content-center"
                    class:active={activeItem === index}
                    on:click={() => setActive(index)}
                >
                    {item.name}
                </a>
            </li>
        {/each}
    </ul>
</div>

接着创建菜单组件中的”/hello”对应文件,在routes目录下创建hello/+page.svelte,在其中随便写点内容。
运行wails dev 就可以看到一个经典侧边栏菜单布局的应用了,点击menu1菜单就可以跳转到相关页面

末尾

在布局完成后,还需要配置一下前端允许访问的外部资源路径。可以看到wails生成的go代码绑定js文件位于src同级的wailsjs目录下,先配置这个路径,执行npm install @types/node,然后在vite.config.js中加入:

...
import path from "path";
...

export default defineConfig({
  ...
  resolve: {
    alias: {
      $wailsjs: path.resolve(__dirname, "./wailsjs"),
    },
  },
  server: {
    fs: {
      allow: ["./wailsjs"],
    },
  },
  ...
});

在前端代码中就可以像这样import * as app from "$wailsjs/go/backend/App";引入wailsjs文件

完整项目可以参考github.com/welllog/otool

ps: 项目比较简陋。如果觉得帮助到您请给个star

本作品采用《CC 协议》,转载必须注明作者和本文链接
~by orinfy
讨论数量: 1
森林

我也写了一个github.com/xusenlin/git-helper
准备等Wails3出来重新弄一下。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!