Complete TypeScript frontend migration #22

Merged
sjg merged 51 commits from feat/typescript-frontend-migration into main 2026-08-01 23:06:19 +02:00
2 changed files with 65 additions and 1 deletions
Showing only changes of commit 42e5dc8604 - Show all commits
+50
View File
@@ -0,0 +1,50 @@
<!--
SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
SPDX-License-Identifier: GPL-2.0-or-later
-->
# TypeScript migration baseline
This baseline records the browser architecture at the start of the migration.
It is intentionally historical; generated output sizes are tracked separately
by the deterministic frontend build.
## Startup order
The initial document loads these scripts in order:
1. `/vendor/opus-decoder-0.7.11.min.js`
2. `/vendor/leaflet.js`
3. `/leaflet-ais-tracksymbol.js`
4. `/webgl-renderer.js`
5. `/ui-core.js`
6. `/app.js`
Decoder and feature scripts are then loaded lazily by the inline loader in
`index.html`. The frontend smoke test locks the core ordering and rejects
remote script or stylesheet URLs.
## Source measurements
At baseline, first-party JavaScript comprised 23 files and approximately
776 KiB. The largest sources were:
| Source | Bytes |
|---|---:|
| `app.js` | 337,111 |
| `map-core.js` | 131,899 |
| `plugins/scheduler.js` | 60,883 |
| `plugins/bookmarks.js` | 30,543 |
| `plugins/sat.js` | 22,541 |
| `plugins/vchan.js` | 20,195 |
| `webgl-renderer.js` | 18,993 |
The migrated source snapshot contained 123 distinct direct `window.*`
assignments. These are compatibility callbacks, shared state, and plugin entry
points. New TypeScript code must not add to that set; the typed plugin registry
and explicit services replace it over the course of the migration.
All production scripts, stylesheets, fonts, icons, and map assets were already
served from local embedded routes. The automated startup test ensures no
remote runtime script or stylesheet dependency is introduced.
@@ -6,7 +6,21 @@ import assert from "node:assert/strict";
import test from "node:test";
import { readFile } from "node:fs/promises";
const indexPath = new URL("../../assets/web/index.html", import.meta.url);
test("index loads the shared UI before the application", async () => {
const html = await readFile(new URL("../../assets/web/index.html", import.meta.url), "utf8");
const html = await readFile(indexPath, "utf8");
assert.ok(html.indexOf("/ui-core.js") < html.indexOf("/app.js"));
});
test("startup has no remote script or stylesheet dependencies", async () => {
const html = await readFile(indexPath, "utf8");
const assetReferences = Array.from(
html.matchAll(/<(?:script|link)\b[^>]+(?:src|href)="([^"]+)"/g),
(match) => match[1],
);
assert.equal(
assetReferences.some((reference) => /^https?:\/\//i.test(reference)),
false,
);
});