Skip to content

Load routes and page copy only when needed - #1839

Merged
stefan-burke merged 17 commits into
mainfrom
perf/lazy-locale-loading
Jul 16, 2026
Merged

stefan-burke merged 17 commits into
mainfrom
perf/lazy-locale-loading

Conversation

@stefan-burke

@stefan-burke stefan-burke commented Jul 15, 2026

Copy link
Copy Markdown
Member

Summary

  • Match request paths before importing their route handlers.
  • Load only the translated copy declared for the matched route.
  • Split broad message catalogs into small groups for each part of the site.
  • Keep one shared request pipeline while loading each admin area only when needed.
  • Keep ticket QR labels and Apple Wallet updates working.

Why

Every request previously imported most route code and built the complete English message catalog during startup. Most pages need only a small part of both. This avoids that unused work while keeping translated message lookup synchronous after a route loads its copy.

Results

  • Combined app-core load improved by 3.4%.
  • Eager top-level evaluation improved by 11.2%.
  • The edge bundle is 879 bytes smaller.
  • /listings keeps the same 28 cold and 23 warm database round trips.

Tests

  • deno task precommit passes with 100% coverage.
  • Route tests cover public, setup, API, admin, attendee, guide, feature-gated, ticket QR, Apple Wallet, contact, and read-only requests.
  • Message ownership is checked on cold and warm requests so routes cannot use undeclared copy.

Mutation-test hardening is intentionally separated into follow-up PR #1849.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR replaces eager English locale merging with lazy message-group loading, adds route-scoped translation visibility, associates groups with application routes, updates admin rendering and test bootstrapping, and adds settings, routing, and wallet validation coverage.

Changes

Lazy i18n routing

Layer / File(s) Summary
Message manifest and i18n state
src/locales/manifest.ts, src/locales/groups.ts, src/locales/en/*.json, src/shared/i18n.ts
Defines message-group manifests and loaders, tracks loaded groups and ownership, deduplicates pending loads, and enforces scoped translation visibility.
Route message-group wiring
src/features/index.ts, src/features/admin/index.ts
Associates groups with route segments and wraps public, setup, API, and admin dispatch in withMessageGroups.
Admin translation render paths
src/features/admin/guide.ts, src/ui/templates/admin/*.tsx
Removes guide-specific loading from handlers and localizes admin page titles from keys at render time.
Catalog validation and test bootstrap
test/shared/*, test/lib/*, test/test-utils/*, scripts/test-harness.ts, scripts/mutation/runner.ts
Updates catalog loading and adds coverage for lazy loading, route scopes, manifest consistency, concurrency, retries, and preload behavior.

Settings bundle safety

Layer / File(s) Summary
Own-prefix settings resolution
src/features/settings-bundles.ts, test/features/settings-bundles.test.ts
Uses own-property detection for prefix settings fallback and tests inherited property handling.

Wallet pass validation

Layer / File(s) Summary
Wallet date field assertion
test/lib/server-wallet-webservice.test.ts
Adds event date data and verifies the generated pass date label.

Mutation attribution maintenance

Layer / File(s) Summary
Equivalent-mutant records
scripts/mutation/equivalent-mutants.txt
Refreshes equivalent-mutant entries for settings bundles, admin dispatch, and i18n locations.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant routeMainApp
  participant withMessageGroups
  participant RouteHandler
  Request->>routeMainApp: dispatch request
  routeMainApp->>withMessageGroups: provide route message groups
  withMessageGroups->>RouteHandler: load groups and execute handler
  RouteHandler-->>Request: return rendered response
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: loading route and page copy lazily only when needed.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/lazy-locale-loading

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/admin/index.ts`:
- Around line 169-188: Both route dispatch tables must reject inherited
prototype properties for attacker-controlled keys. In
src/features/admin/index.ts lines 169-188, update the segmentRouters lookup in
the route dispatch flow to require Object.hasOwn(segmentRouters, segment) before
using segmentRouter; in src/features/index.ts lines 517-525, apply the
equivalent own-property guard to prefixHandlers[prefix] within routeMainApp.
Preserve the existing not-found behavior for missing entries.

In `@test/lib/i18n-route-loading.test.ts`:
- Around line 9-16: Consolidate the duplicated i18n cold-reset and
message-restoration logic by reusing the existing shared helper from
test/shared/i18n-loading.test.ts. Update withColdMessages and the related
withCommonLoader setup to delegate through that helper, preserving the
resetI18nForTest(true), try/finally restoration, and MESSAGE_GROUPS behavior
without retaining duplicate inline boilerplate.
- Line 1: Extract the repeated reset/restore flow into one exported shared test
helper in the existing `#test-utils` area, reusing resetI18nForTest and
ensureMessageGroups. Keep or move withColdMessages from
i18n-route-loading.test.ts to use this helper, and update withCommonLoader plus
the other cold-reset test sites in i18n-loading.test.ts to delegate to it while
retaining only their loader-specific setup and restoration.

In `@test/shared/i18n-loading.test.ts`:
- Around line 15-29: Refactor withCommonLoader to reuse the shared helper used
by the route-loading test’s withColdMessages instead of duplicating loader
replacement, cold-reset, restoration, and ensureMessageGroups cleanup. Preserve
the helper’s temporary ENGLISH_MESSAGE_LOADERS.common override and guaranteed
restoration behavior.
- Around line 32-49: Replace the duplicated reset-and-restore setup in the test
"loads only the requested message group" with the shared helper or fixture used
for the consolidated cold-reset/restore pattern. Preserve the test’s assertions
and ensure all message groups are restored after execution.
- Around line 51-64: Replace the duplicated reset-and-restore setup in the test
“keeps messages and compiled formats when another group loads” with the shared
cold-reset/restore helper or pattern referenced by the consolidated review
comment, while preserving the existing assertions and cleanup behavior.

In `@test/test-utils/i18n.ts`:
- Around line 12-17: Update the catalog aggregation in the i18n test utility
around ENGLISH_MESSAGE_LOADERS to track which group owns each message key and
throw immediately when a key appears in more than one loaded catalog, instead of
using Object.assign’s last-write-wins behavior. Preserve the existing merged
result for catalogs without duplicate keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8909b62e-7cf4-450b-8f03-fad03b7eba22

📥 Commits

Reviewing files that changed from the base of the PR and between cf3e660 and 6c7aed1.

📒 Files selected for processing (29)
  • scripts/mutation/equivalent-mutants.txt
  • scripts/mutation/runner.ts
  • scripts/test-harness.ts
  • src/features/admin/guide.ts
  • src/features/admin/index.ts
  • src/features/index.ts
  • src/locales/en/common.json
  • src/locales/en/guide.ts
  • src/locales/en/index.ts
  • src/locales/en/public.json
  • src/locales/en/system.json
  • src/locales/groups.ts
  • src/locales/manifest.ts
  • src/shared/guide-messages.ts
  • src/shared/i18n.ts
  • src/ui/templates/admin/admin-page.tsx
  • src/ui/templates/admin/backup.tsx
  • src/ui/templates/admin/builder.tsx
  • src/ui/templates/admin/update.tsx
  • test/lib/i18n-coverage.test.ts
  • test/lib/i18n-route-loading.test.ts
  • test/shared/guide-messages.test.ts
  • test/shared/i18n-loading.test.ts
  • test/shared/i18n.test.ts
  • test/shared/listing-defaults.test.ts
  • test/shared/settings/forms.test.ts
  • test/test-utils/i18n.ts
  • test/test-utils/preload.ts
  • test/ui/templates/admin/guide/schema.test.ts
💤 Files with no reviewable changes (5)
  • src/locales/en/guide.ts
  • src/shared/guide-messages.ts
  • src/locales/en/index.ts
  • test/shared/guide-messages.test.ts
  • src/locales/en/public.json

Comment thread src/features/admin/index.ts Outdated
Comment thread test/lib/i18n-route-loading.test.ts
Comment thread test/lib/i18n-route-loading.test.ts Outdated
Comment thread test/shared/i18n-loading.test.ts Outdated
Comment thread test/shared/i18n-loading.test.ts Outdated
Comment thread test/shared/i18n-loading.test.ts Outdated
Comment thread test/test-utils/i18n.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 93e3a41d95

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/index.ts Outdated
Comment thread src/features/admin/index.ts Outdated
Comment thread src/features/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/shared/i18n.ts`:
- Around line 64-75: Update the catalog processing around the extra-entry loop
to validate all entries into temporary collections before mutating messages or
owners. Only commit the temporary entries after validation succeeds, ensuring
rejected catalogs leave no earlier keys registered; add a regression test
confirming previously encountered keys remain unavailable after a non-string or
duplicate entry causes rejection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e214bcd5-41e0-4592-9af5-04555b0fb57a

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7aed1 and 0a67f5e.

📒 Files selected for processing (12)
  • scripts/mutation/equivalent-mutants.txt
  • src/features/admin/index.ts
  • src/features/index.ts
  • src/features/settings-bundles.ts
  • src/shared/i18n.ts
  • test/features/settings-bundles.test.ts
  • test/lib/i18n-route-loading.test.ts
  • test/lib/owner-footer.test.ts
  • test/lib/server-misc-routing.test.ts
  • test/lib/server-wallet-webservice.test.ts
  • test/shared/i18n-loading.test.ts
  • test/test-utils/i18n.ts

Comment thread src/shared/i18n.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/mutation/equivalent-mutants.txt`:
- Around line 954-957: Update the survivor-count header for this i18n
mutation-attribution block from five to four, leaving all four listed entries
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 01d053ee-55ec-4aaa-bd0c-83938e68021b

📥 Commits

Reviewing files that changed from the base of the PR and between 8cada9a and 61eefee.

📒 Files selected for processing (3)
  • scripts/mutation/equivalent-mutants.txt
  • src/shared/i18n.ts
  • test/shared/i18n-loading.test.ts

Comment thread scripts/mutation/equivalent-mutants.txt
@stefan-burke stefan-burke changed the title Load page copy only when routes need it Load routes and page copy only when needed Jul 16, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5bf30af7f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/route-prefixes.ts Outdated
@stefan-burke
stefan-burke added this pull request to the merge queue Jul 16, 2026
@stefan-burke
stefan-burke removed this pull request from the merge queue due to a manual request Jul 16, 2026
@stefan-burke
stefan-burke added this pull request to the merge queue Jul 16, 2026
Merged via the queue into main with commit a5df1b6 Jul 16, 2026
2 checks passed
@stefan-burke
stefan-burke deleted the perf/lazy-locale-loading branch July 16, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant