Skip to content

Commit 210e992

Browse files
committed
Address reviews so far.
1 parent 095c427 commit 210e992

File tree

3 files changed

+64
-18
lines changed

3 files changed

+64
-18
lines changed

doc/tutorial/getting-started/index.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@ title: Getting Started with Scala.js, Vite, Laminar and ScalablyTyped
55

66
This series of tutorials teaches you how to use Scala.js together with modern development tools.
77

8+
1. [Scala.js and Vite](./scalajs-vite.html):
9+
* Set up a hello world project ready for live reloading in the browser.
10+
* Generate minimized production assets.
11+
2. [Laminar and ScalablyTyped](./laminar-scalablytyped.html):
12+
* Build UIs with Laminar using Function Reactive Programming (FRP), a hybrid model between imperative and functional programming particularly well suited for UI development in Scala.
13+
* Integrate JavaScript libraries using ScalablyTyped.
14+
815
If you have time, reading and applying them in order will give you more in-depth knowledge about the development environment.
916

1017
If you are in a hurry, you can skip the ones you are not interested in.
11-
Each tutorial starts with a link to repo that you can clone to get off the ground.
18+
Each tutorial starts with a link to a repo that you can clone to get off the ground.
1219

1320
In any case, make sure that you have the Prerequisites listed below covered.
1421

15-
## Tutorials
16-
17-
1. [Scala.js and Vite](./scalajs-vite.html): set up a hello world project ready for live reloading in the browser.
18-
2. [Laminar and ScalablyTyped](./laminar-scalablytyped.html): build UIs with Laminar, and integrate JavaScript libraries with ScalablyTyped.
19-
2022
## Prerequisites
2123

2224
In any case, make sure that you have the following tools installed first:

doc/tutorial/getting-started/laminar-scalablytyped.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ If you prefer to navigate the end result for this tutorial directly, checkout [t
1212

1313
## Prerequisites
1414

15-
Make sure to install [the prerequisites](./index.html) before continuing further.
15+
Make sure to install [the prerequisites](./index.html#prerequisites) before continuing further.
1616

1717
## Introducing Laminar
1818

19+
[Laminar](https://laminar.dev/) is a Scala.js library to build UIs using Functional Reactive Programming (FRP).
20+
FRP is a hybrid model between imperative and functional programming.
21+
It is particularly well suited to developing UIs in Scala, as we can reason about relationships between immutable values while dealing with the changing nature of the UI.
22+
We will elaborate on this point later.
23+
1924
To start off, we add a dependency on Laminar in our `build.sbt`:
2025

2126
{% highlight diff %}
@@ -35,7 +40,7 @@ sbt:livechart> ~fastLinkJS
3540
[...]
3641
{% endhighlight %}
3742

38-
If it was already running, stop it and `reload` it for changes in `build.sbt` to take effect.
43+
If sbt was already running, run `reload` for the changes in `build.sbt` to take effect, then start the incremental compiler with `~fastLinkJS`.
3944

4045
Additionally, start Vite's development server if it wasn't already running:
4146

@@ -44,7 +49,7 @@ $ npm run dev
4449
[...]
4550
{% endhighlight %}
4651

47-
We can now change the contents of `src/main/scala/livechart/LiveChart.scala` to use Laminar instead of raw DOM APIs.
52+
We can now change the contents of `src/main/scala/livechart/LiveChart.scala` to use Laminar instead of vanilla DOM APIs.
4853

4954
At the top, we use the following import:
5055

@@ -142,6 +147,11 @@ We then use it in two *bindings*:
142147
We do not need to explicitly set the `innerHTML` attribute of the button.
143148
That is taken care of by the `<--` binding.
144149

150+
Unlike frameworks based on a virtual DOM, Laminar bindings directly target the DOM element to update.
151+
With a virtual DOM, when the value of `counter` changes, we would build an entirely new VDOM representation for the button (and perhaps its parents), and the framework would later diff it and identify which DOM `HTMLButtonElement` to update.
152+
In Laminar, however, the `<--` binding remembers the precise instance of `HTMLButtonElement` to update, and directly modifies its text.
153+
This is more efficient than going through the VDOM indirection.
154+
145155
Beside `:=`, the two binding arrows `<--` and `-->` are the only symbolic operators that Laminar defines.
146156
`:=` is a static binding.
147157
It can be seen as a `<--` with a time-immutable value on the right.

doc/tutorial/getting-started/scalajs-vite.md

+43-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ title: Getting Started with Scala.js and Vite
44
---
55

66
In this first tutorial, we learn how to get started with Scala.js and [Vite](https://vitejs.dev/).
7-
We use Vite to provide live-reloading of the Scala.js application in the browser.
7+
We use Vite to provide live-reloading of the Scala.js application in the browser for development.
8+
We also configure it to build a minimal bundle for production.
89

910
Going through this tutorial will make sure you understand the basic building blocks.
1011
If you prefer to skip this step and directly write Scala.js code, you may jump to [Getting Started with Scala.js and Laminar](./laminar-scalablytyped.html).
@@ -13,25 +14,25 @@ If you prefer to navigate the end result for this tutorial directly, checkout [t
1314

1415
## Prerequisites
1516

16-
Make sure to install [the prerequisites](./index.html) before continuing further.
17+
Make sure to install [the prerequisites](./index.html#prerequisites) before continuing further.
1718

1819
## Vite template
1920

2021
We bootstrap our setup using the vanilla Vite template.
2122
Navigate to a directory where you store projects, and run the command
2223

2324
{% highlight shell %}
24-
$ npm create vite@latest
25+
$ npm create vite@3.2.1
2526
{% endhighlight %}
2627

2728
Choose a project name (we choose `livechart`).
2829
Select the "Vanilla" framework and the "JavaScript" variant.
2930
Our output gives:
3031

3132
{% highlight shell %}
32-
$ npm create vite@latest
33+
$ npm create vite@3.2.1
3334
Need to install the following packages:
34-
create-vite@latest
35+
create-vite@3.2.1
3536
Ok to proceed? (y)
3637
✔ Project name: … livechart
3738
✔ Select a framework: › Vanilla
@@ -156,9 +157,9 @@ import scala.scalajs.js.annotation.*
156157

157158
import org.scalajs.dom
158159

159-
// import javaScriptLogo from "/javascript.svg"
160+
// import javascriptLogo from "/javascript.svg"
160161
@js.native @JSImport("/javascript.svg", JSImport.Default)
161-
val javaScriptLogo: String = js.native
162+
val javascriptLogo: String = js.native
162163

163164
@main
164165
def LiveChart(): Unit =
@@ -168,7 +169,7 @@ def LiveChart(): Unit =
168169
<img src="/vite.svg" class="logo" alt="Vite logo" />
169170
</a>
170171
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank">
171-
<img src="$javaScriptLogo" class="logo vanilla" alt="JavaScript logo" />
172+
<img src="$javascriptLogo" class="logo vanilla" alt="JavaScript logo" />
172173
</a>
173174
<h1>Hello Scala.js!</h1>
174175
<div class="card">
@@ -198,6 +199,39 @@ end setupCounter
198199
Note that the above is not idiomatic Scala, but rather a direct translation of the Vite template code into Scala.js.
199200
We will see in the next tutorial how to use Laminar to write it more idiomatically.
200201

202+
For the most part, the Scala.js version uses straightforward Scala syntax corresponding to the original JavaScript code.
203+
The definition of `javascriptLogo` deserves some explanation.
204+
205+
We translated it from the JavaScript import
206+
207+
{% highlight javascript %}
208+
import javascriptLogo from "/javascript.svg"
209+
{% endhighlight %}
210+
211+
which is actually a shorthand for
212+
213+
{% highlight javascript %}
214+
import { default as javascriptLogo } from "/javascript.svg"
215+
{% endhighlight %}
216+
217+
Many bundlers, Vite included, treat `import`s with asset files such as `.svg` as pseudo-modules whose `default` import is the *file path* to the corresponding asset in the processed bundle.
218+
Further down, we use it as the value for the `src` attribute an `<img>` tag.
219+
Read more about this mechanism [in the Vite documentation on static asset handling](https://vitejs.dev/guide/assets.html).
220+
221+
The translation in Scala.js reads as
222+
223+
{% highlight scala %}
224+
@js.native @JSImport("/javascript.svg", JSImport.Default)
225+
val javascriptLogo: String = js.native
226+
{% endhighlight %}
227+
228+
The `@js.native` annotation tells Scala.js that `javascriptLogo` is provided externally by JavaScript.
229+
The `@JSImport("/javascript.svg", JSImport.Default)` is the translation of the `default` import from the `/javascript.svg` pseudo-module.
230+
Since it represents a file path, we declare `javascriptLogo` as a `String`.
231+
232+
The `= js.native` is a Scala.js idiosyncrasy: we need a concrete value to satisfy the Scala typechecker.
233+
In an ideal world, it would not be required.
234+
201235
We can now build the Scala.js project by opening a new console, and entering sbt:
202236

203237
{% highlight shell %}
@@ -309,7 +343,7 @@ export default defineConfig({
309343
{% endhighlight %}
310344

311345
While this may look scary, most of the complexity is concentrated into `printSbtTask`.
312-
That utility invokes a third-party process (sbt) in a platform-independent way (in particular, for Windows) and retries its `stdout` output.
346+
That utility invokes a third-party process (sbt) in a platform-independent way (in particular, for Windows) and retrieves its `stdout` output.
313347
Other than that, we are doing two things:
314348

315349
1. Depending on `process.env.NODE_ENV`, we retrieve the output of the sbt task `fastLinkJSOutput` or `fullLinkJSOutput`.

0 commit comments

Comments
 (0)