From a8f92b46f477e955a200e19401c96ec8cc1bbf9b Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 9 Sep 2024 16:26:28 +0200 Subject: [PATCH] Add article about including Gleam from HTML --- content/using-gleam-in-html-low-js.rst | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 content/using-gleam-in-html-low-js.rst diff --git a/content/using-gleam-in-html-low-js.rst b/content/using-gleam-in-html-low-js.rst new file mode 100644 index 0000000..5cce643 --- /dev/null +++ b/content/using-gleam-in-html-low-js.rst @@ -0,0 +1,94 @@ +Using Gleam in HTML with as little JavaScript knowledge as possible +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +:slug: using-gleam-in-html-low-js +:date: 2024-09-09 16:28 +:tags: gleam, software, web +:category: programming +:keywords: javascript module, gleam, frontend +:lang: en +:translation: false +:status: published + +I've been looking at the `Gleam language `__ recently. Among other features, it can be compiled to JavaScript, and thus presumably used on web frontend. I wanted to try that. This is a short tutorial on how to do that with little idea how JavaScript is supposed to work. + +My initial JS knowledge: ``alert(3)``, ``onclick`` and some basic selectors, i.e. the little stuff that is useful to add minor interactivity to HTML pages and implement trivial ViolentMonkey scripts. Namely: I have no knowledge about modules and whatnot, and this post is just a result of my trial-and-error attempt at embedding my Gleam. I succeeded, but still have no idea what I am doing :-) + +My code +======= +Let's start with some trivial code, in ``src/lol.gleam`` (in a project initialised with ``gleam new lol`` and the ``repeatedly`` package added with ``gleam add repeatedly``):: + + import gleam/io + import repeatedly + + pub fn say_hello() { + repeatedly.call(2000, Nil, fn(_state, _call) {io.println(get_greeting())}) + } + + pub fn get_greeting() { + "Hello World!" + } + + pub fn main() { + io.println("3, 2, 1, go!") + } + +This snippet has many of the basic stuff I might need in future: it does some io, it uses another package [#stdlib-package]_, it returns data I will want to show. At first I am mostly interested in multiplatform stuff (i.e. running also on the BEAM backend), so I don't want to use any DOM frameworks at first, though I will mention some of the ways later in the post. + +So, build this for JavaScript: ``gleam build --target javascript``, and *stuff happens*. It is not very clear what to do now, but ``grep``ping through the ``build/`` directory shows that the built code lives in ``build/dev/javascript/lol/lol.mjs``. + +Embedding the code +================== + +Here comes the fun part: the code is in JavaScript *module*, not plain code. That comes with several surprises: +- It can only be imported from other modules, not by “plain” code in global scope +- Due to CORS, imports only work with network schemes, not with the ``file://`` one +- Due to scoping, I have not found a way of using the functions from devtools console + +Big wins for the platform /s, but we have to live with that, so let's try to write the respective HTML for this. I put that in ``main.html`` in the project root, but it does not probably matter. The code:: + + + + + + Buh + + + + +

+ + + + + + +Shoutout to `the person who asked the same question on StackOverflow `__. From this point on, we only need a HTTP server; luckily, Python has one in stdlib, so just calling ``python3 -m http.server 12312`` in the project root lets us load ``http://localhost:12312/main.html`` and see our page. + +Next steps, alternatives et cetera +================================== + +When developing web frontend in Gleam, the more common way is using a framework like `Lustre `__ or at least a DOM library (there are `several `__, I have no idea how mature those are). I did not go this route yet, because I am more interested in using backend-agnostic Gleam code from JavaScript and don't mind writing the trivial bindings in JavaScript. [#netzpevnik-gleam]_ + +Also, a common thing to do is using a minifier+bundler like `esgleam `__ (it uses `esbuild `__ under the hood), so that the whole project is in one file. I don't think I need that now (having the JS be readable is more important to me atm and I don't want to complicate things further), but there is at least `one tutorial `__ on how to do that. + +Also, during writing of this article I realised Gleam can run all the JS code from itself, so I could have a ``js_main`` function that would bind the HTML from Gleam itself. But this is probably more readable and separated anyway. + +------- + +.. [#stdlib-package] Well, as far as I understand it, Gleam's stdlib is actually just another package anyway. + +.. [#netzpevnik-gleam] I will probably use some kind of framework eventually as a part of `netzpevnik `__, but I am exploring the technologies that will be involved, so I want to keep stuff simple.