From adce7ff9470a71a8fec7d3ca5f3b850733a83e32 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 31 Aug 2026 10:49:52 -0400 Subject: [PATCH] feat: npm-tier example with no server JS and no config tag (#261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit examples/11-npm-local is Old Faithful (app.py + app.R over one client) at the npm tier with nothing else on the page. Where examples/09-hmr uses `set_react_page(shinyreact_js="client")` — which omits the JS but still emits the `#shinyreact-config` tag — this app's whole page is `page_bare(page_react_dep(...))`, so it has: - no shinyreact.js, hence one React and one hook registry on the page; - no config tag, hence no protocol handshake. The client imports `@posit/shinyreact` from the repo-relative `file:../../pkg-js` placeholder, the same one 09-hmr uses until the first npm publish. The second half is a deletion. The config-tag strict mode — a missing tag, or a tag with no `protocolVersion`, throwing rather than logging — existed only for the npm build, on the reasoning that an independently installed client meeting a tagless page means the server predates the protocol. It also banned the simplest page there is. Nothing opts into it now, so `requireShinyReactConfigTag()`, `isShinyReactConfigTagRequired()`, their flag and their test-only reset are gone, along with the two branches in bookmark.ts. A tag with no `protocolVersion` still logs; a major-version mismatch still throws visibly, in both builds. --- FEATURES.md | 33 ++- decisions/2026-08-17-js-distribution.md | 18 +- examples/09-hmr/app.py | 3 +- examples/11-npm-local/.gitignore | 4 + examples/11-npm-local/FEATURES.md | 78 +++++ examples/11-npm-local/README.md | 71 +++++ examples/11-npm-local/app.R | 45 +++ examples/11-npm-local/app.py | 65 +++++ examples/11-npm-local/faithful.csv | 273 ++++++++++++++++++ examples/11-npm-local/package.json | 18 ++ examples/11-npm-local/src/ui.css | 27 ++ examples/11-npm-local/src/ui.jsx | 70 +++++ examples/11-npm-local/tests/test_page.py | 45 +++ examples/11-npm-local/tests/testthat.R | 10 + .../11-npm-local/tests/testthat/test-page.R | 48 +++ examples/11-npm-local/vite.config.js | 33 +++ examples/README.md | 15 +- examples/testing/mount.ts | 2 - pkg-js/dist/shinyreact.js | 10 +- pkg-js/package-lock.json | 4 +- pkg-js/package.json | 4 +- pkg-js/src/__tests__/entry-parity.test.ts | 17 -- pkg-js/src/npm.ts | 6 - .../__tests__/use-shiny-restore.test.tsx | 31 +- pkg-js/src/shiny-react/bookmark.ts | 34 +-- pkg-js/src/shiny-react/config.ts | 21 -- pkg-py/src/shinyreact/_dep.py | 3 +- pkg-py/src/shinyreact/_page.py | 4 +- pkg-py/src/shinyreact/www/shinyreact.js | 10 +- pkg-r/R/dep.R | 2 +- pkg-r/R/page.R | 5 +- pkg-r/inst/lib/shiny/shinyreact.js | 10 +- pkg-r/man/page_react.Rd | 5 +- pkg-r/tests/testthat/test-examples.R | 14 +- 34 files changed, 876 insertions(+), 162 deletions(-) create mode 100644 examples/11-npm-local/.gitignore create mode 100644 examples/11-npm-local/FEATURES.md create mode 100644 examples/11-npm-local/README.md create mode 100644 examples/11-npm-local/app.R create mode 100644 examples/11-npm-local/app.py create mode 100644 examples/11-npm-local/faithful.csv create mode 100644 examples/11-npm-local/package.json create mode 100644 examples/11-npm-local/src/ui.css create mode 100644 examples/11-npm-local/src/ui.jsx create mode 100644 examples/11-npm-local/tests/test_page.py create mode 100644 examples/11-npm-local/tests/testthat.R create mode 100644 examples/11-npm-local/tests/testthat/test-page.R create mode 100644 examples/11-npm-local/vite.config.js diff --git a/FEATURES.md b/FEATURES.md index fe6f767d..b703082a 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -85,8 +85,9 @@ R has no e2e suite, so no `(e2e)` leaf covers R (issue #194). reported is that client and server cannot talk - one element reused across repeated failures; the newest message wins - the throw is unchanged (fail fast); the banner is additive - - covers all three fatal paths: major mismatch (either direction), missing - tag in the npm build, and a tag with no `protocolVersion` in the npm build + - covers the only fatal path there is: a major-version mismatch (either + direction). A missing tag, or a tag with no `protocolVersion`, is not + fatal in either build - server → client boot config: one `