plihelix / wails-template-sveltekit

Wails.io template using SvelteKit - trades SSR for golang within the app
https://github.com/plihelix/wails-sveltekit
40 stars 1 forks source link
static-adapter svelte sveltekit wails wails-sveltekit wails-template

This is the Unofficial Wails Svelte Kit Static-Adapter blank template.

... and ...

How-To Build any Svelte Kit Front End in Wails. (or others!)

This is a minimally invasive template remix of Wails.io to support SvelteKit out of the box. This results in a pretty straightforward addition of many useful features of Svelte Kit such as routing to a Wails.io app.

Why is the static site adapter needed in Svelte Kit and not Svelte?

The first thing to understand is that Vite is a web-server which is used for the dev mode. Wails uses this to locally host a website with live reload for development mode, which the application navigates to. This is commonly used for all the top frameworks and has robust features such as server side rendering(ssr).

The default configuration of Vite for Svelte Kit projects includes ssr. But, this is normal for web served applications using server compute for more "consistent" web user experience by sending server rendered html to the client. This is more consistent than an api call to that same server, yes. But in a wails app, we're packaging the UI in the binary itself.

This means that unlike Vite, wails doesn't provide a web-server with a Javascript back end built in. It uses the appropriate webclient to provide the Javascript runtime.

Dependencies:

Install:

wails init -n MYAPP -t https://github.com/plihelix/wails-template-sveltekit

Live Development

To run in live development mode, run wails dev in the project directory. This will run a Vite development server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect to this in your browser, and you can call your Go code from devtools.

The adapter combined with the option not to do server side rendering builds the site into the frontend/build directory which is embedded into the application during wails build or file referenced during dev mode. I find this to be great for live development stability; any error which stops a rebuild, avoids getting sent to the wails app webclient. Save early, save often with less fear.

Building

To build a redistributable, production mode package, use wails build.

What's the difference? Why not just use Svelte?

As already mentioned, server side rendering of html content moves API calls that the client would request and then need to format into the webpage skeleton to the server. There are various reasons you may want this capability, but at it's core ssr seeks to provide a user experience that feels more like a locally run app. By moving the api calls into the server farm, the user doesn't need to load the page and then stare at a blank page waiting on product data to show up. This makes for a more consistent user experience on everything from mobile to hpc.

Wails, however, is for building applications that run on a users device with a golang back end and an embedded front end. The idea here is the opposite from ssr; the target client is expected to do some or all of the work, but is provided the assets. The commonality is in placing the work with the data. Wails with svelte is already pretty smooth at building sites dynamically around the data you provide it with.

The addition of routing should not be understated. Basically, the big advantage to SvelteKit over svelte in wails is the routing. Since you have these endpoints for pages and can navigate through them you don't have to build a one-page app like svelte does; you can effectively load and unload modular parts of an interface.

If the app is complex, let's say you were building your own 2d slider game, a one page app becomes a behemoth to contend with handling all the various flags and cross-talk. The fact that it only loads once, means that wails has to throw a flag to hide one pseudo-page to and unhide another. You probably want the hidden one to stop taking a steam of data. If you want it to be quick and snappy, you've got to do all that cleanup yourself.

On this game, you want to do a bunch of levels with different art? You can probably imagine the monstrosity of 30+ level designs, art, menus, and all packed into a single page in memory terms let alone the design nightmare to manage it.

Using SvelteKit, the user can just navigate to the new endpoint. Automatically unloading the old page and cleaning up connections, while loading in just what you need. Just like wails svelte, the page is built around the data provided to it as it's loaded. So, for this example, the controls and hud can be loaded from their own endpoints, each level from it's own.

How to install any SvelteKit frontend into a new Wails project.

Init your new project as normal

I used the svelte base just in case I am misunderstanding how this all works together.

Remove the new MYAPP/frontend folder:

cd MYAPP
rm -r ./frontend

Use npm create to generate a new /frontend from a template: (eg:)

npm create svelte@latest frontend

npm create skeleton-app@latest frontend

Note: I don't see why this wouldn't be the go-to choice with most; since wails uses generated ts as well. The choices here will only matter if you open the project in your editor at the /frontend or use their commands from within the front end folder.

Here is where we can replicate the main issue people have when attempting to use Wails with SvelteKit.

Both are accessed by the web kit just like any website. Allowing for all of the clientside js in the svelte page, but not the code that would run on the server in a js runtime environment. A default Svelte Kit project in the /frontend folder expects a Vite to do server side rendering and included server side Javascript out of the /frontend/[src] directories. Wails can take advantage of this in dev mode because Vite is doing the work, it just navigates to the web socket.

If you compile now with wails build, you'll see the dreaded Can't find index.html message.

If you get "Can't find index.html" after a compile:

check main.go for what is being embedded

How to run off ssr with adapter-static.

Go into the front end folder and install the dependencies adding @sveltejs/adapter-static.

cd frontend
npm i -D @sveltejs/adapter-static

Edit the svelte.config.js file.

// Change from adapter-auto to adapter-static
import adapter from '@sveltejs/adapter-static';
// Other imports may be present depending on your template.
import preprocess from "svelte-preprocess";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  // SvelteKit's section:
  kit: {
    adapter: adapter({
      // Static needs a fallback page.
      fallback: 'index.html'
    })
  },
  // (Vite's section):
  // Others:
  preprocess: [
    preprocess({
      postcss: true,
    }),
  ],
}

export default config;

How to get access to the wailsjs folder:

In wails.json, the following option controls where wails places the wailsjs/ directory. For easiest use, simply direct it into the default library alias for SvelteKit.

"wailsjsdir": "./frontend/src/lib",

While its probably best to just create this folder and reference it via $lib/wailsjs/go/.../App.js, I'm going to go ahead and show how to create an @ link that begins at frontend/.

Edit the frontend/tsconfig.json or frontend/jsconfig.json file and add paths to the bottom of the "compilerOptions":.

"paths": {
  // Overwrites the defaults and $lib is required for svelte-kit.
  "$lib": ["src/lib"],
  "$lib/*": ["src/lib/*"],

  // Adds the ability to import from the `frontend/` folder.
  "@/*": ["*"]
}

Edit the frontend/vite.config.js file:

import { sveltekit } from '@sveltejs/kit/vite';
import path from 'path'

/** @type {import('vite').UserConfig} */
const config = {
  server: {
    fs: {
      // Allow serving files from the frontend project root
      allow: ['.'],
    },
  },
    plugins: [sveltekit()],
  resolve: {
    alias: {
      // This alias finishes the ability to reference our
      // frontend/ with `@path/to/file`.
      //
      '@': path.resolve(__dirname, './'), 
    },
  },
};

export default config;

Don't forget to include .sveltekit in your git or you'll probably have trouble after cloning as it is required.

There is a simple shell script to do this with SkeletonUI located in its own repo. Feel free to customize to your needs!

That's it, go back to the root of the project and run wails dev or wails build. Enjoy!