feat(ui): unsupported-engine boot screen; drop the temporary diagnostic
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m6s
CI / conformance (pull_request) Successful in 8s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m55s

Replace the temporary on-device boot diagnostic (the always-on overlay, the
console.error mirror and the handleError console hook) with a permanent boot-capability
guard in index.html. Before the deferred module, in plain ES5, it:
  - hard-gates on the unpolyfillable essentials the app cannot run without — BigInt (the
    64-bit FlatBuffers wire decode) and Proxy (Svelte 5 runes) — and, when one is
    missing, shows a friendly full-screen "this device's OS/browser can't run the app"
    screen instead of a white screen;
  - soft-gates the polyfillable es2020+ globals, pulling core-js (polyfills.js) only
    when needed (the previous behaviour, folded in);
  - keeps a reactive net: an uncaught error during boot with no window.__booted signal
    within 8s raises the same screen with the captured cause.
Inside a Telegram/VK Mini App the screen also points to the web version
(https://<host>/app/). A "Diagnostic information" button reveals the engine, the
feature table, the reason and the app version, with a Copy button.

App.svelte sets window.__booted once bootstrap resolves. vite.config drops the
now-unneeded strip-boot-diag plugin and adds inject-boot-version (stamps the guard's
diagnostic with VITE_APP_VERSION). The es2019 target, the core-js loader and the board
cqw->vmin glyph fallback stay. The speculative Chrome-74 pan change is reverted — it did
not fix the judder and added nothing on modern engines.

Verified: svelte-check clean, unit + mock e2e green (the guard is inert on a capable
engine, so the size budget and the smoke are untouched), and the screen + diagnostic +
stamped version render on a forced hard-gate (BigInt removed via addInitScript).

The unsupported-engine telemetry beacon (dedup + edge rate-limit + a Prometheus counter)
is a separate follow-up PR, per the agreed split.
This commit is contained in:
Ilia Denisov
2026-07-04 20:23:19 +02:00
parent 8499f388af
commit 2729fe9467
5 changed files with 248 additions and 400 deletions
+11 -15
View File
@@ -4,19 +4,17 @@ import { defineConfig, type Plugin } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
/**
* stripBootDiag removes the temporary on-device boot-diagnostic block from index.html — the span
* between the `<!-- BOOT-DIAG:START -->` and `<!-- BOOT-DIAG:END -->` markers. That block is a
* full-screen ES5 overlay meant only for the production build shipped to the test contour, so it
* is dropped from every non-production build: the `mock` e2e (whose first taps the overlay would
* intercept) and the dev server. It is wired only when mode !== 'production'. Remove this plugin
* together with the index.html block once the Android WebView diagnosis is finished — it must
* never reach master / production.
* injectBootVersion stamps the app version into index.html's boot-capability guard, replacing its
* __BOOT_VERSION__ placeholder with the same VITE_APP_VERSION build-arg that feeds __APP_VERSION__.
* The guard runs before the bundle, so it cannot read the bundle's version; this lets its on-demand
* diagnostic report name the client version anyway. Falls back to "dev" for a local build.
*/
function stripBootDiag(): Plugin {
function injectBootVersion(): Plugin {
const version = process.env.VITE_APP_VERSION || 'dev';
return {
name: 'strip-boot-diag',
name: 'inject-boot-version',
transformIndexHtml(html) {
return html.replace(/\s*<!-- BOOT-DIAG:START[\s\S]*?BOOT-DIAG:END -->/g, '');
return html.replace(/__BOOT_VERSION__/g, version);
},
};
}
@@ -56,11 +54,9 @@ export default defineConfig(({ mode }) => ({
// so a missing build-arg never breaks the build.
__APP_VERSION__: JSON.stringify(process.env.VITE_APP_VERSION || 'dev'),
},
// emitPolyfills always ships dist/polyfills.js (loaded only by old engines; see its docstring
// and the index.html gate). The boot-diagnostic overlay ships only in the production build (the
// test contour) — it is stripped from the dev server and the mock e2e build, where a full-screen
// overlay would intercept Playwright's taps. See stripBootDiag / the index.html BOOT-DIAG block.
plugins: [svelte(), emitPolyfills(), ...(mode !== 'production' ? [stripBootDiag()] : [])],
// emitPolyfills ships dist/polyfills.js (loaded only by old engines; see its docstring + the
// index.html boot guard). injectBootVersion stamps the app version into that guard's diagnostic.
plugins: [svelte(), emitPolyfills(), injectBootVersion()],
server: {
port: 5173,
proxy: