Creating an Electron application with Svelte 3 and TypeScript - Part 1

Note This article is a part of a series of tutorials "Creating an Electron application with Svelte 3 and TypeScript".

Earlier this month the team behind the web UI framework Svelte announced they are now officially supporting TypeScript. I didn't follow the project before this announcement, but I see it as a good motivation to try it out. For this reason I decided I would create a simple Electron application interfacing with Wikipedia's public API, and will document the process through a serie of tutorials.

I read Svelte's documentation yesterday for the first time, so I'm really new to the framework, though from what I've seen so far it should be quite fast to pick up. As mentioned in the title, I'm going to use Svelte 3 and TypeScript. Let's start with the initial setup.

Setup Svelte 3 + TypeScript

Getting started with Svelte may be a bit confusing, as for literally everything in the web world there is an infinite amount of options available for every single task, which can be overwhelming. In general I like to have complete control over my tooling, but I recently had a quite good exprience doing the exact opposite when working with Expo on HabitCat, so I decided to do the same here and see how it goes with what seem to be the easiest and fastest way to get something running. The best way I found to setup an initial Svelte project is documented in this Getting Started guide written by Rich Harris, Svelte's original author (and still the main maintainer I believe?). Just follow the template instructions, and you quickly have a running environment based on a Rollup setup. Support for TypeScript just require an additional step during the setup, then we're good to go.

So all together:

$ npx degit sveltejs/template MyApp
$ cd MyApp
$ node scripts/setupTypeScript.js
$ npm install
$ npm run build
# And voila!

Surprisingly, everything worked as expected, no outdated dependencies or weird errors when trying to build the project or start the developer tools, so that's already a quite good experience (though of course yours may vary).

Setup Electron

We want Electron, so let's just add it to our list of dependencies.

$ npm install --save-dev electron

That's optional, but I'm also adding two small utilities that help keep the amount of boilerplate relatively low when working on Electron projects:

  • cross-env - cross-platform support for env vars
  • npm-run-all - small tool to run NPM scripts in parallel or sequential
$ npm install --save-dev cross-env
$ npm install --save-dev npm-run-all

Once done, add an electron.js file in your src directory (of course feel free to name it as you want), with the minimal logic to get started with an Electron app:

// src/electron.js

const { app, BrowserWindow } = require("electron")
const path = require("path")

let mainWindow

function createWindow() {
	mainWindow = new BrowserWindow({
		width: 900,
		height: 680,
	})

	const mode = process.env.NODE_ENV
	const url =
		mode === "production"
    		// in production, use the statically build version of our application
    		? `file://${path.join(__dirname, "../public/index.html")}`
    		// in dev, target the host and port of the local rollup web server
    		: "http://localhost:5000"
	mainWindow.loadURL(url)
	mainWindow.on("closed", () => {
		mainWindow = null
	})
}

app.on("ready", createWindow)

// those two events completely optional to subscrbe to, but that's a common way to get the
// user experience people expect to have on macOS: do not quit the application directly
// after the user close the last window, instead wait for Command + Q (or equivalent).
app.on("window-all-closed", () => {
	if (process.platform !== "darwin") app.quit()
})
app.on("activate", () => {
	if (mainWindow === null) createWindow()
})

We don't use TypeScript here, but that's a detail for now, that's not the part I want to focus on, let's just get up and running so that we can work on our application.

Ok, all of this should be good, let's register our init file in package.json:

// package.json

{
  ...,
  "version": "1.0.0",
  "main": "./src/electron.js", // <= Add this line somewhere close to the top
  ...,
}

And let's also define NPM tasks to easily start our dev environment and build our application:

// package.json

{
    "scripts": {
        ...
        "dev-electron": "run-p dev start-electron", // <= run-p is from "npm-run-all" and will start both tasks in parallel
        "build-electron": "run-s build start-electron", // <= run-s is from "npm-run-all" and will start both tasks in sequential
        "start-electron": "electron ." // <= here we define our default parameters to start electron
    },
    ...
}

That's it for the setup and for this initial blog article, you can now start the electron dev environment by running npm run dev-electron, with live editing support.

In the follow-up articles I will document the creation of our main pages and components, a simple routing implementation, interfacing with the MediaWiki API, etc. In the mean time, you can already start hacking on the project 😉.

Update

The second part is now available, follow the project implementation there:

Part 2 - Define our goals and implement an interactive search bar