complete performance and reliability follow-ups

This commit is contained in:
2026-08-09 23:04:36 +05:30
parent 8f19a5eb2b
commit 232d8e6734
31 changed files with 525 additions and 726 deletions
+12 -73
View File
@@ -66,12 +66,12 @@ import type { StoreDefinition } from "@wrnexus/store";
import type { ClientRuntimeDefinition } from "@wrnexus/plugin";
import { CacheCoordinator } from "@wrnexus/cache";
import { generateServiceWorker } from "@wrnexus/pwa";
import { runtimeScriptsForMarkup } from "./plugin-assets.ts";
import { collectScripts, usesMobileRuntime } from "./script-selection.ts";
export { collectScripts, usesMobileRuntime } from "./script-selection.ts";
import {
ACCENT_COOKIE,
THEME_COOKIE,
THEME_CSS_HREF,
THEME_JS_HREF,
activeThemeCssHref,
resolveAccentName,
resolveThemeName,
type MobileConfig,
@@ -81,7 +81,6 @@ import {
type TenancyConfig,
} from "@wrnexus/styles";
import {
I18N_JS_HREF,
renderI18nData,
makeT,
resolveLang,
@@ -945,9 +944,6 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
headParts.push(
`<link rel="stylesheet" href="${versionAssetUrl("/__wrnexus/framework.css", deps.assetVersion)}" />`,
);
} else if (deps.theme && !deps.stylesIncludeFramework) {
const themeHref = versionAssetUrl(THEME_CSS_HREF, deps.assetVersion);
headParts.push(`<link rel="stylesheet" href="${themeHref}" />`);
}
if (deps.hasUi && !deps.hasFrameworkStyles && !deps.stylesIncludeFramework) {
headParts.push(
@@ -1839,6 +1835,7 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
// <html> attributes: no-flash theme (from cookie, validated) + active lang.
const attrs: string[] = [];
let activeThemeHead = "";
if (deps.theme) {
const themeName = resolveThemeName(ctx.cookies.get(THEME_COOKIE), deps.theme);
@@ -1850,6 +1847,13 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
if (accentName) {
attrs.push(`data-accent="${accentName}"`);
}
if (!deps.hasFrameworkStyles && !deps.stylesIncludeFramework) {
const themeHref = versionAssetUrl(
activeThemeCssHref(themeName, accentName),
deps.assetVersion,
);
activeThemeHead = `<link rel="stylesheet" data-wrnexus-theme href="${themeHref}" />`;
}
}
attrs.push(`lang="${safeLanguageTag(language)}"`);
if (deps.i18n) attrs.push(`dir="${deps.i18n.direction[language] ?? "ltr"}"`);
@@ -1873,6 +1877,7 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
pwaEnabled ? `<link rel="manifest" href="/site.webmanifest" />` : "",
pwaEnabled ? `<meta name="mobile-web-app-capable" content="yes" />` : "",
pwaEnabled ? `<meta name="apple-mobile-web-app-capable" content="yes" />` : "",
activeThemeHead,
extraHead,
]
.filter(Boolean)
@@ -2443,72 +2448,6 @@ export function normalizeComponentName(name: string): string {
return name.toLowerCase().replace(/[-_]/g, "");
}
/**
* Decide which framework scripts a rendered page needs. Components are already
* server-rendered into the HTML; the only script is the reactive runtime, and
* only when the page actually contains a scope or a browser-side API fetch.
*/
export function collectScripts(
body: string,
clientRuntimes: readonly ClientRuntimeDefinition[] = [],
navigation: { mode?: "auto" | "client" | "document" } = {},
): RenderScript[] {
const scripts: RenderScript[] = [];
if (
/\bdata-scope=/.test(body) ||
/\bdata-wrnexus-csr=/.test(body) ||
/\bdata-wrn-client-template=/.test(body) ||
/\bdata-wrn-async=/.test(body)
) {
scripts.push("/__wrnexus/reactive.js");
}
if (/\bdata-wrn-action=/.test(body)) scripts.push("/__wrnexus/actions.js");
// The theme runtime is only needed when the page can switch themes.
if (
/\bdata-wire-theme-(toggle|set)\b/.test(body) ||
/\bdata-wire-accent-(set|clear)\b/.test(body)
) {
scripts.push(THEME_JS_HREF);
}
// Validation: schema descriptors + the generic validator, only for pages with a form.
if (/\bdata-schema="[A-Za-z0-9_-]+"/.test(body)) {
scripts.push("/__wrnexus/schemas.js", "/__wrnexus/validate.js");
}
// Language switcher runtime, only when the page has one.
if (/\bdata-wire-lang-set\b/.test(body) || /\bselect[^>]*\bdata-wire-lang\b/.test(body)) {
scripts.push(I18N_JS_HREF);
}
// Realtime client, only when the page declares a room.
if (/\bdata-room=/.test(body)) {
scripts.push("/__wrnexus/realtime.js");
}
// File-upload runtime (drag-drop + progress), only when a page has an uploader.
if (/\bdata-uploader\b/.test(body)) {
scripts.push("/__wrnexus/uploader.js");
}
// Package runtimes are declarative. Components mark the rendered HTML with
// `data-wrnexus-runtime="id"`; the corresponding package chunk is loaded
// once, without requiring application-authored script tags or public copies.
scripts.push(...runtimeScriptsForMarkup(body, clientRuntimes));
// `auto` is the performance-first default: a fully static page ships no
// framework JavaScript and its links use native document navigation. Routes
// that already need browser behavior also receive progressive navigation.
// `client` preserves the explicit always-on behavior; `document` disables it.
const mode = navigation.mode ?? "auto";
if (mode === "client" || (mode === "auto" && scripts.length > 0)) {
scripts.unshift("/__wrnexus/nav.js");
}
return scripts;
}
/** Whether rendered markup needs the Capacitor/native browser bridge. */
export function usesMobileRuntime(body: string): boolean {
return /\b(?:data-mobile-[\w-]+|data-native-(?:browser|mobile|only|requires|unsupported|options)|data-on-wrnexus-(?:browser|mobile)-[\w-]+)\b/.test(
body,
);
}
function safeLanguageTag(value: string): string {
return /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/.test(value) ? value : "en";
}