Let's make a App with Scala.js and Tauri part 1
Tauri is a framework for building tiny, fast binaries for all major desktop and mobile platforms. Javascript app will run as if it was running within browser. Let’s make a simple application using scala.js.
Requirements for Tauri
Build tools for each platform, rust and node.js must be installed first. See tauri’s document.
Creation of an application
Tauri supports ways of creating app’s skeleton. We’ll use pnpm
. Install it before running following commands. When it runs, it will ask questions to answer. Enter your own identifier for second question.
1
2
3
4
5
6
7
>> pnpm create tauri-app
✔ Project name · tauri-app
✔ Identifier · <your unique identifier>
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
✔ Choose your package manager · pnpm
✔ Choose your UI template · Vanilla
✔ Choose your UI flavor · JavaScript
CD into the project folder and install packages. Then make an application and run it. A window with icons and simple form will be shown.
1
2
3
>> cd tauri-app
>> pnpm instal
>> pnpm tauri dev
Structure of the project folder
Simplified structure of the project folder with important files are as follows
1
2
3
4
5
6
7
8
+- src : where our javascript app will be located
| - index.html : skeleton of app
| - main.js : javascript referenced in index.html
+- src-tauri : tauri's code in rust
| - Cargo.toml : build configuration for rust
| - tauri.conf.json : our tauri app's meta information and configuration
+- node_modules : handled by pnpm
- package.json : package file for node.js
Let Scala render the screen
Now it’s time for scala.js. I will use mill as a build tool and scalatags for HTML. Welcome to Li Haoyi world.
install mill
As mill’s installation page, the standard method of installing mill is to install mill script at project folder. I’ve had problem running mill in Windows and had to edit mill.bat
to change default mill version. Following will work in macOS and linux.
1
2
3
>> curl -L https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/0.13.0-M0/mill -o mill
>> chmod +x mill
>> echo 0.12.8 > .mill-version
Mill’s build file is build.sc
and mill requires separate source folder.
1
2
3
>> touch build.sc
>> mkdir -p front/src
>> touch front/src/Front.scala
build.sc
Object front
in build.sc
matches the folder name. All source files, resources and test files reside within that folder. fscala
task compiles scala code and copies the resulting javascript codes to src
folder. mill
’s build file is using scala 2.13 syntax, so square brackets are needed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import mill._, scalalib._, scalajslib._
object front extends ScalaJSModule {
def scalaVersion = "3.6.3"
def scalaJSVersion = "1.18.2"
def ivyDeps = Agg(ivy"com.lihaoyi::scalatags::0.13.1")
def fscala = Task {
val jsPath = front.fastLinkJS().dest.path
val targetPath = jsPath / os.up / os.up / os.up / "src"
val target = targetPath / "main.js"
os.copy.over(jsPath / "main.js", target)
os.copy.over(jsPath / "main.js.map", targetPath / "main.js.map")
PathRef(target)
}
}
Front.scala
Using scalatags to render into document’s boby. The structure of tags are same as original index.html.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.scalajs.dom
import scalatags.JsDom.all.*
object Front:
def main(args: Array[String]): Unit =
// render tags into body
dom.document.body.appendChild(content.render)
val content =
tag("main")(cls := "container",
h1(s"Welcome to Tauri with Scala.js"),
div(cls := "row",
a(href := "https://tauri.app",
target := "_blank",
img(src := "/assets/tauri.svg", cls := "logo tauri", alt := "Tauri logo")),
a(href := "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
target := "_blank",
img(src := "/assets/javascript.svg", cls := "logo vanilla", alt := "JavaScript logo"))
),
p("Click on the Tauri logo to learn more about the framework"),
form(cls := "row", id := "greet-form",
input(id := "greet-input", placeholder := "Enter a name..."),
button(`type` := "submit", "Greet")),
p(id := "greet-msg")
)
index.html
Remove all tags in body.
1
2
3
4
5
6
7
8
9
10
11
12
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
<script type="module" src="/main.js" defer></script>
</head>
<body>
</body>
</html>
First line compiles scala to javascript code and copy it to src
folder.
1
2
>> ./mill front.fscala
>> pnpm tauri dev
Now app’s appearance is same as initial code, but screen is rendered from scala code. Greet button does not work as previously. This functionality requires calling Tauri’s API, which will be handled at part 2.