nandi/frqpublic Fork 0
87a28ccbc1ad41565d24fa8c4f68e1f9426fd61e
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

README.md · 79 lines · 3.6 KBmarkdown Blame HistoryRaw
A third target, and the seam that was already waiting for it f54ca45 nandi 2d ago1# `flutter-web`
2
3 modal run .modal/flutter-web/container.py
4 just modal flutter-web
5
6Defined by `container.toml`; see `../spec.md` for the keys.
Three tarballs where a devShell was 5ce66d5 nandi yesterday7Built on `debian:13-slim`.
8
9No nix, and that is the point of this container rather than an
10incidental fact about it. The build is `tools/build-web.sh`, which
11gets its Flutter, its JDK and its Clojure CLI from
12`tools/toolchain.sh` -- three tarballs pinned by sha256 and unpacked
13into a directory. So the image build is one `apt-get install` of
14curl, git, rsync, tar and the two unarchivers, and everything that
15used to happen before a line of Dart was compiled -- warming a
16devShell, printing its environment, caching that against flake.lock,
17copying a nix closure back to a volume afterwards -- does not happen
18at all. The toolchain lands on the volume and the second run finds
19it there.
20
21The other two Flutter targets keep their devShells: `apk` needs the
22Android SDK and `flutter-desktop` needs GTK and a C++ toolchain, and
23a host toolchain is what nix is better at than a tarball. The web
24target needs a Dart and a JVM, which is what a tarball is for.
25
26Same incremental shape as before -- the working tree, the generated
27Dart under `flutter/lib/cljd-out` and Flutter's caches live on the
28`devshell` volume, under `frq-flutter-web/` so the desktop
29container's directory beside it is untouched. None of them is copied
30in from the laptop: a checkout's copy of the compiler's output is
31not this container's, and overwriting the volume's with it is how an
32incremental build stops being one.
33
34One build mode, not two. A `fast` mode (dart2js -O1, no icon
35tree-shaking, no service worker) measured 52.5s against the release
36build's 49.8s on the same source change, so what it bought was a
37bigger bundle. `--no-wasm-dry-run` is the flag that did pay, and it
38is in the one build there is.
A third target, and the seam that was already waiting for it f54ca45 nandi 2d ago39
40Runs as a Sandbox on a real VM (kernel 6.x, not gVisor). The command
41is the sandbox's own process, so it dies when the command exits.
42
43To look at what it built, ask for the serve action -- `[network]
44ports` tunnels 8080 out, and the URL is printed once the sandbox is
45scheduled:
46
47 modal run .modal/flutter-web/container.py \
Three tarballs where a devShell was 5ce66d5 nandi yesterday48 --command 'cd /devshell/frq-flutter-web && tools/build-web.sh serve 8080'
A third target, and the seam that was already waiting for it f54ca45 nandi 2d ago49
50That blocks until you Ctrl-C it, and it bills until you do.
51
52## It compiles; it does not start
53
54dart2js links the whole app -- `main.dart.js` is 3.6MB and has
55`frq`, `irc`, `atproto` and `handshake` all through it, so the
56`dart:io` imports under `flutter/src` are not the wall they look
57like. What stops it is the first line of `main`:
58`getApplicationDocumentsDirectory` is a platform channel, path_provider
59ships no web implementation, and the channel with no handler behind it
60throws `MissingPluginException`. `main` awaits that before installing
61`frq.io.dart`, so no widget is ever built and the page stays white.
62
63That is the seam doing its job rather than a build problem. The fix is
64a `frq.io.web` behind `frq.io` -- the browser's answer for a private
65file is IndexedDB or localStorage, not a directory -- and `main`
66choosing it the way `flutter/src/frq/main.cljd` chooses the Dart one
67now. `frq.net.web` is the next one after it, for the same reason: a
68browser has no raw socket, so the IRC connection wants a WebSocket.
69
70## Serving it
71
72`serve.py` is the other half: a Function that mounts the same volume
73and hands out `flutter/build/web`, so a rebuild in the Sandbox is
74picked up by the next cold start with nothing redeployed.
75
76 modal deploy .modal/flutter-web/serve.py
77
78`[network] ports` tunnels 8080 out of the Sandbox as well, for the
79case where you want the build and the server to be one process.