Skip to content

Add webjs.clientRouter:false opt-out for the automatic client router #629

@vivek7405

Description

@vivek7405

Problem

As of #620 the client router auto-enables whenever @webjsdev/core loads in the browser (any page that ships a component), and layouts no longer import @webjsdev/core/client-router. That removed the only de-facto opt-out an app had (omitting the import). An app that genuinely wants pure MPA / full-page navigation despite shipping interactive components now has no declarative way to turn the router off.

This is intentionally deferred from #620 (no users to break yet, and automatic navigation is the stated thesis), but it should exist before external adoption.

Design / approach

A package.json webjs.clientRouter: false config key (default true). Because the auto-enable runs in the shared webjs-core-browser.js bundle (client-side), the server must communicate the opt-out to the browser:

  • Server reads webjs.clientRouter (the standard webjs.* 3-place lockstep: schema + WebjsConfig type + a reader), and when false emits a tiny inline signal BEFORE the boot module script (e.g. <script>window.__webjs_no_router__=true</script>, or a <html data-webjs-no-router> attribute) so it is set before the deferred module bundle evaluates.
  • The router's module-end auto-enable (packages/core/src/router-client.js) guards on that signal: if (no-router flag) return; instead of calling enableClientRouter().
  • disableClientRouter() stays the programmatic escape hatch.

Implementation notes (for the implementing agent)

  • Config (server AGENTS.md "The webjs package.json config block", 3 places + drift test): packages/server/webjs-config.schema.json, packages/core/src/webjs-config.d.ts (WebjsConfig), a reader (e.g. in dev.js), and KNOWN_KEYS in test/config/webjs-config-schema.test.js.
  • Emit seam: ssr.js boot/shell assembly (it already emits the importmap + WEBJS_PUBLIC_ inline script + boot module). The flag must be in the document BEFORE the boot <script type="module"> (module scripts are deferred, so an inline classic script in <head>/early <body> runs first).
  • Router gate: packages/core/src/router-client.js module-end enableClientRouter() call (added/made explicit in dogfood: auto-enable client router via webjs-core-browser.js, drop layout imports #620 via index-browser.js). Read the flag with a typeof window guard.
  • Tests: a browser/unit test that the flag suppresses the auto-enable (counterfactual: absent flag enables); a config drift test; an e2e/integration asserting webjs.clientRouter:false yields full-page navigation.
  • Docs: the client-router doc page + AGENTS.md (note the opt-out), once it lands.
  • Invariant: the DEFAULT (absent / any non-false value) must be byte-identical to today's automatic-on behaviour.

Acceptance criteria

  • webjs.clientRouter: false disables the client-router auto-enable (full-page navigation), config wired in schema + type + reader + drift test
  • Default and any non-false value keep the router automatic (unchanged)
  • The flag is emitted before the boot module so it is honored on first load
  • Browser/e2e test proves both states, with a counterfactual
  • Docs note the opt-out

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions