@rshono/core 1.0.0-rc.12 → 1.0.0-rc.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +29 -8
- package/bin/rshono.mjs +3 -4
- package/dist/builder/env-shadow-loader.cjs +25 -6
- package/dist/builder/page-files.js +5 -5
- package/dist/builder/page-files.js.map +1 -1
- package/dist/builder/public-env.d.ts +5 -4
- package/dist/builder/public-env.d.ts.map +1 -1
- package/dist/builder/public-env.js +5 -4
- package/dist/builder/public-env.js.map +1 -1
- package/dist/builder/react-versions.d.ts +13 -0
- package/dist/builder/react-versions.d.ts.map +1 -0
- package/dist/builder/react-versions.js +74 -0
- package/dist/builder/react-versions.js.map +1 -0
- package/dist/builder/rspack-config.d.ts +5 -11
- package/dist/builder/rspack-config.d.ts.map +1 -1
- package/dist/builder/rspack-config.js +73 -55
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +6 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +30 -40
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +5 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +12 -16
- package/dist/cli/start.js.map +1 -1
- package/dist/config.d.ts +28 -31
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/deploy/aws-lambda/runtime.d.ts +4 -6
- package/dist/deploy/aws-lambda/runtime.d.ts.map +1 -1
- package/dist/deploy/aws-lambda/runtime.js +5 -8
- package/dist/deploy/aws-lambda/runtime.js.map +1 -1
- package/dist/deploy/build-marker.d.ts +3 -5
- package/dist/deploy/build-marker.d.ts.map +1 -1
- package/dist/deploy/build-marker.js +3 -5
- package/dist/deploy/build-marker.js.map +1 -1
- package/dist/deploy/cloudflare/build.d.ts.map +1 -1
- package/dist/deploy/cloudflare/build.js +6 -10
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts +2 -5
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +19 -32
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +25 -42
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +3 -5
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +15 -11
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +4 -5
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +9 -15
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +19 -29
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +41 -24
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/vercel/build.d.ts.map +1 -1
- package/dist/deploy/vercel/build.js +19 -16
- package/dist/deploy/vercel/build.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts +4 -7
- package/dist/deploy/vercel/runtime.d.ts.map +1 -1
- package/dist/deploy/vercel/runtime.js +13 -7
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -12
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +65 -93
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +2 -5
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +24 -30
- package/dist/runtime/boundaries.d.ts.map +1 -1
- package/dist/runtime/boundaries.js +15 -22
- package/dist/runtime/boundaries.js.map +1 -1
- package/dist/runtime/client.d.ts +16 -7
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +16 -7
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +89 -118
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +122 -167
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.js +3 -3
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/dev-protocol.d.ts +4 -8
- package/dist/runtime/dev-protocol.d.ts.map +1 -1
- package/dist/runtime/dev-protocol.js.map +1 -1
- package/dist/runtime/entry.client.js +121 -113
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts +5 -6
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +140 -129
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +7 -12
- package/dist/runtime/entry.ssr.d.ts.map +1 -1
- package/dist/runtime/entry.ssr.js +13 -24
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +10 -17
- package/dist/runtime/flight-inject.d.ts.map +1 -1
- package/dist/runtime/flight-inject.js +63 -54
- package/dist/runtime/flight-inject.js.map +1 -1
- package/dist/runtime/hot-update.d.ts +20 -27
- package/dist/runtime/hot-update.d.ts.map +1 -1
- package/dist/runtime/hot-update.js +17 -23
- package/dist/runtime/hot-update.js.map +1 -1
- package/dist/runtime/navigation.d.ts +14 -19
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js +9 -13
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +16 -10
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +30 -10
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +18 -10
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +21 -19
- package/dist/runtime/server.js.map +1 -1
- package/dist/server/headers.d.ts +8 -15
- package/dist/server/headers.d.ts.map +1 -1
- package/dist/server/headers.js +8 -15
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +2 -2
- package/dist/server/load-config.d.ts.map +1 -1
- package/dist/server/load-config.js +6 -9
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/prerendered.d.ts +40 -45
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +50 -33
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +13 -28
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +5 -10
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/shutdown.d.ts +5 -3
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/server/shutdown.js +5 -3
- package/dist/server/shutdown.js.map +1 -1
- package/dist/server/ssg.d.ts +3 -6
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +12 -21
- package/dist/server/ssg.js.map +1 -1
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lasse Tange
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -15,10 +15,12 @@ One required file (`src/routes.ts`), one optional file (`src/server.ts`), and yo
|
|
|
15
15
|
streaming SSR with RSC hydration, server actions with progressive enhancement, soft navigation, build-time
|
|
16
16
|
prerendering, and hard env/secret safety.
|
|
17
17
|
|
|
18
|
-
> **
|
|
19
|
-
> Rspack's
|
|
20
|
-
> `
|
|
21
|
-
> versions and a release of rshono is what moves them
|
|
18
|
+
> **Release candidate.** The framework itself is covered end to end (see [Testing](#testing)) and its API is
|
|
19
|
+
> settled. What is not settled underneath it: Rspack's RSC support is an experimental API
|
|
20
|
+
> (`rspack.experiments.rsc`) and `react-server-dom-rspack` is still `0.0.x`. Both are pinned to exact
|
|
21
|
+
> versions — in the manifests and in workspace overrides — and a release of rshono is what moves them, so an
|
|
22
|
+
> upstream change reaches you as a tested release rather than as a broken install. That is the whole of the
|
|
23
|
+
> caveat, and it is the reason to read the [changelog](../../CHANGELOG.md) before upgrading.
|
|
22
24
|
|
|
23
25
|
**Full documentation: [rshono.com/docs](https://www.rshono.com/docs).**
|
|
24
26
|
|
|
@@ -221,7 +223,7 @@ that runs this, the environment is what sets them. [Configuration docs](https://
|
|
|
221
223
|
|
|
222
224
|
The defaults, in short: untrusted proxy headers, `nosniff` / `Referrer-Policy` / `X-Frame-Options` on
|
|
223
225
|
every response (a floor your own `secureHeaders()` overrides),
|
|
224
|
-
`private, no-cache` plus `Vary:
|
|
226
|
+
`private, no-cache` plus `Vary: RSC` on dynamic pages, `public, max-age=300` and a weak `ETag` on
|
|
225
227
|
prerendered ones, and errors redacted in production — with one `onServerError()` funnel for reporting them
|
|
226
228
|
and three fallbacks (a fatal client overlay, a visible 500 document, a reported bootstrap failure) so a
|
|
227
229
|
failure is never a blank screen.
|
|
@@ -263,7 +265,19 @@ Every target streams, which is the bar a new one has to clear.
|
|
|
263
265
|
on Vercel, `streamifyResponse` plus a `RESPONSE_STREAM` Function URL on Lambda. Getting those right is what
|
|
264
266
|
the presets are for.
|
|
265
267
|
- **Prerendered pages are never CDN-served**: one URL answers with a document or a flight payload depending on
|
|
266
|
-
`
|
|
268
|
+
the `RSC` request header, and a path-keyed CDN cannot choose. `/_static` and `public/` do go straight to the
|
|
269
|
+
CDN.
|
|
270
|
+
- **The serverless targets bundle your dependencies**; `node` bundles only the ones a `'use client'` component
|
|
271
|
+
pulls in. A function is an uploaded directory with no `node_modules` to resolve against, so `vercel`,
|
|
272
|
+
`aws-lambda` and `cloudflare` compile everything in. The cost is that a native addon — or a package that
|
|
273
|
+
reads its own files off disk — fails the build on those targets rather than the deploy; reach for the
|
|
274
|
+
`rspack` hook, or deploy to `node`.
|
|
275
|
+
|
|
276
|
+
On `node` a server component's dependencies stay external and resolve from `node_modules`, but anything
|
|
277
|
+
reachable from a `'use client'` component is compiled in on every target. It has to be: the `PUBLIC_`-only
|
|
278
|
+
`process.env` view is applied by a loader, and a loader cannot run on a module the bundle only imports by
|
|
279
|
+
name — an external third-party client component would be SSR'd against the real environment. Nothing is
|
|
280
|
+
given up, since the same module is in the browser bundle and so was always required to be bundleable.
|
|
267
281
|
|
|
268
282
|
[Deployment docs](https://www.rshono.com/docs/deployment), including Cloudflare bindings and the AWS setup.
|
|
269
283
|
|
|
@@ -274,6 +288,11 @@ Every target streams, which is the bar a new one has to clear.
|
|
|
274
288
|
`react-server-dom-rspack` requires).
|
|
275
289
|
- No response compression, no base path (`siteUrl` is a bare origin), and wildcard, optional and regex
|
|
276
290
|
params cannot be prerendered.
|
|
291
|
+
- **No link prefetching**, by choice: a link is one fetch at click time and nothing before it. Speculative
|
|
292
|
+
fetching on hover spends every visitor's bandwidth to help some of them — so a navigation here costs a
|
|
293
|
+
round trip that Next.js and TanStack Start have usually already paid.
|
|
294
|
+
- No incremental static regeneration: `render: 'static'` is decided at build time, and a static page changes
|
|
295
|
+
when you rebuild.
|
|
277
296
|
- Scroll restoration is the browser's (`history.scrollRestoration = 'auto'`).
|
|
278
297
|
- The dev proxy doesn't forward WebSocket upgrades to a custom sub-app; production is unaffected.
|
|
279
298
|
- Dev source maps embed the original source of `'use server'` modules (dev binds 127.0.0.1 only, and
|
|
@@ -313,5 +332,7 @@ Two coordinated Rspack compilers, using native RSC support (`rspack.experiments.
|
|
|
313
332
|
In dev the CLI watches both bundles, runs the server bundle in a worker thread (restarted per rebuild,
|
|
314
333
|
requests gated on readiness so nothing drops), and fronts everything on one port with static serving and an
|
|
315
334
|
SSE channel: client edits hot-apply via react-refresh, server component edits re-fetch the payload in place,
|
|
316
|
-
and browser state survives both. In production `dist/server/main.mjs`
|
|
317
|
-
|
|
335
|
+
and browser state survives both. In production `dist/server/main.mjs` has React, Hono and the framework
|
|
336
|
+
bundled in. On `node` your server-side dependencies still resolve from `node_modules` beside it; on the
|
|
337
|
+
serverless targets they are bundled too, because nothing installs them there. Whatever a `'use client'`
|
|
338
|
+
component reaches is bundled on every target, which is what lets the env shadow cover it.
|
package/bin/rshono.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Thin launcher for the compiled CLI. Everything
|
|
3
|
-
//
|
|
2
|
+
// Thin launcher for the compiled CLI. Everything here has to happen before the CLI module graph loads, which is
|
|
3
|
+
// why the import at the bottom is dynamic.
|
|
4
4
|
const args = process.argv.slice(2);
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
// value is read during config resolution and baked into the bundle, so it has to be set this early.
|
|
6
|
+
// The production commands default NODE_ENV, which is read during config resolution and baked into the bundle.
|
|
8
7
|
if ((args[0] === 'build' || args[0] === 'start') && !process.env.NODE_ENV) {
|
|
9
8
|
process.env.NODE_ENV = 'production';
|
|
10
9
|
}
|
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/** Whitespace and comments — what may sit before or between directives without ending the prologue. */
|
|
4
|
+
const TRIVIA = '(?:\\s|//[^\\n]*(?:\\n|$)|/\\*[\\s\\S]*?\\*/)*';
|
|
5
|
+
/** One directive: `'use strict'`, `"use client"`, `'use server'`. The backreference keeps the quotes matched. */
|
|
6
|
+
const DIRECTIVE = '([\'"])use [a-z -]+\\1\\s*;?';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The whole directive prologue, so the prelude below is inserted *after* every directive rather than after the
|
|
10
|
+
* first one.
|
|
11
|
+
*
|
|
12
|
+
* The repetition is load-bearing. A module with two directives — `"use strict"` beside `'use client'`, which is
|
|
13
|
+
* ordinary output from a published component library, in either order — would otherwise take the prelude
|
|
14
|
+
* *between* them, and a directive preceded by a statement is just an expression: whichever came second would
|
|
15
|
+
* silently stop being a directive. That was survivable while this loader only saw the app's own hand-written
|
|
16
|
+
* source, where `'use client'` comes first and alone; it stopped being survivable when the rule widened to
|
|
17
|
+
* cover `node_modules` (see the SSR-layer rule in `rspack-config.ts`).
|
|
18
|
+
*
|
|
19
|
+
* Each repetition has to consume a whole directive, so the nested quantifiers cannot loop on an empty match.
|
|
20
|
+
*/
|
|
21
|
+
const DIRECTIVE_PROLOGUE = new RegExp(`^${TRIVIA}(?:${DIRECTIVE}${TRIVIA})*`);
|
|
3
22
|
|
|
4
23
|
/**
|
|
5
24
|
* Shadows `process.env` with the PUBLIC_-only view inside SSR-layer modules, so a secret read from a
|
|
6
|
-
* `'use client'` component renders empty on the server
|
|
7
|
-
*
|
|
25
|
+
* `'use client'` component renders empty on the server rather than leaking into the HTML stream — and SSR
|
|
26
|
+
* keeps agreeing with hydration, which sees the same view via DefinePlugin.
|
|
8
27
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
28
|
+
* A security control, so it fails the build rather than passing source through when it cannot confirm a
|
|
29
|
+
* module's layer: `_module` is a private Rspack field, and a silent no-op if it were renamed would drop the
|
|
30
|
+
* guarantee with nothing to notice.
|
|
12
31
|
*/
|
|
13
32
|
module.exports = function envShadowLoader(source) {
|
|
14
33
|
if (!source.includes('process.env')) return source;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the
|
|
3
|
-
*
|
|
4
|
-
* `'use server-entry'` directive
|
|
2
|
+
* Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the server
|
|
3
|
+
* compiler can put `page-entry-loader.cjs` in front of exactly those files. A page wired up any other way
|
|
4
|
+
* declares its `'use server-entry'` directive itself.
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, statSync } from 'node:fs';
|
|
7
7
|
import { dirname, join, resolve } from 'node:path';
|
|
8
8
|
const COMPONENT_THUNK = /component:\s*(?:async\s*)?\(\s*\)\s*=>\s*import\(\s*(['"])([^'"]+)\1\s*\)/g;
|
|
9
9
|
const EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];
|
|
10
|
-
//
|
|
11
|
-
//
|
|
10
|
+
// `join` rather than `base + '/index…'`: these are compared against Rspack's own resource paths, which on
|
|
11
|
+
// Windows carry backslashes.
|
|
12
12
|
function resolveCandidates(base) {
|
|
13
13
|
return [...EXTENSIONS.map((ext) => base + ext), ...EXTENSIONS.map((ext) => join(base, `index${ext}`)), base];
|
|
14
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-files.js","sourceRoot":"","sources":["../../src/builder/page-files.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,eAAe,GAAG,4EAA4E,CAAC;AAErG,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAElD,
|
|
1
|
+
{"version":3,"file":"page-files.js","sourceRoot":"","sources":["../../src/builder/page-files.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,eAAe,GAAG,4EAA4E,CAAC;AAErG,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAElD,0GAA0G;AAC1G,6BAA6B;AAC7B,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/G,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,MAAc,EAAE,IAAiB;IACjF,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAwB,CAAC;QAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;aAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,MAAM,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the server\n * compiler can put `page-entry-loader.cjs` in front of exactly those files. A page wired up any other way\n * declares its `'use server-entry'` directive itself.\n */\nimport { readFileSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nconst COMPONENT_THUNK = /component:\\s*(?:async\\s*)?\\(\\s*\\)\\s*=>\\s*import\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/g;\n\nconst EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];\n\n// `join` rather than `base + '/index…'`: these are compared against Rspack's own resource paths, which on\n// Windows carry backslashes.\nfunction resolveCandidates(base: string): string[] {\n return [...EXTENSIONS.map((ext) => base + ext), ...EXTENSIONS.map((ext) => join(base, `index${ext}`)), base];\n}\n\nfunction isFile(path: string): boolean {\n try {\n return statSync(path).isFile();\n } catch {\n return false;\n }\n}\n\nexport function scanPageFiles(routesFile: string, srcDir: string, into: Set<string>): void {\n into.clear();\n let source: string;\n try {\n source = readFileSync(routesFile, 'utf8');\n } catch {\n return;\n }\n for (const match of source.matchAll(COMPONENT_THUNK)) {\n const spec = match[2];\n let base: string | undefined;\n if (spec.startsWith('.')) base = resolve(dirname(routesFile), spec);\n else if (spec.startsWith('@/')) base = resolve(srcDir, spec.slice(2));\n if (!base) continue;\n for (const candidate of resolveCandidates(base)) {\n if (isFile(candidate)) {\n into.add(candidate);\n break;\n }\n }\n }\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* modules with, so the server renders
|
|
2
|
+
* The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.
|
|
3
|
+
* A stray read of anything else in client code becomes `undefined` rather than shipping the value.
|
|
4
|
+
*
|
|
5
|
+
* Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser
|
|
6
|
+
* hydrates.
|
|
6
7
|
*/
|
|
7
8
|
export declare function publicEnv(isDev: boolean): Record<string, string>;
|
|
8
9
|
//# sourceMappingURL=public-env.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-env.d.ts","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"public-env.d.ts","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGhE"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* modules with, so the server renders
|
|
2
|
+
* The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.
|
|
3
|
+
* A stray read of anything else in client code becomes `undefined` rather than shipping the value.
|
|
4
|
+
*
|
|
5
|
+
* Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser
|
|
6
|
+
* hydrates.
|
|
6
7
|
*/
|
|
7
8
|
export function publicEnv(isDev) {
|
|
8
9
|
const entries = Object.entries(process.env).filter((entry) => entry[0].startsWith('PUBLIC_') && entry[1] !== undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-env.js","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"public-env.js","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACnJ,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.\n * A stray read of anything else in client code becomes `undefined` rather than shipping the value.\n *\n * Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser\n * hydrates.\n */\nexport function publicEnv(isDev: boolean): Record<string, string> {\n const entries = Object.entries(process.env).filter((entry): entry is [string, string] => entry[0].startsWith('PUBLIC_') && entry[1] !== undefined);\n return { NODE_ENV: isDev ? 'development' : 'production', ...Object.fromEntries(entries) };\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the
|
|
3
|
+
* version this release was tested with.
|
|
4
|
+
*
|
|
5
|
+
* The mismatch is an error because it never works. A different minor is only a warning: upstream declares
|
|
6
|
+
* `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a
|
|
7
|
+
* React release — a worse failure than the one it would prevent.
|
|
8
|
+
*
|
|
9
|
+
* @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the
|
|
10
|
+
* framework's.
|
|
11
|
+
*/
|
|
12
|
+
export declare function checkReactVersions(rootDir: string): void;
|
|
13
|
+
//# sourceMappingURL=react-versions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-versions.d.ts","sourceRoot":"","sources":["../../src/builder/react-versions.ts"],"names":[],"mappings":"AA6CA;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyBxD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one dependency check the framework makes on an app: that `react` and `react-dom` are the same build.
|
|
3
|
+
*
|
|
4
|
+
* React Server Components couple the two across bundles — `react-server-dom-rspack` reaches into
|
|
5
|
+
* `ReactSharedInternals` and emits a flight payload the *matching* `react-dom` has to parse — so a split
|
|
6
|
+
* resolution is not version skew to be tolerated. It is a crash inside minified React at render time, with
|
|
7
|
+
* nothing in the message pointing at the cause.
|
|
8
|
+
*
|
|
9
|
+
* The monorepo prevents it with `overrides` in `pnpm-workspace.yaml` and `packages/create` pins both exactly
|
|
10
|
+
* for the same reason, because a generated app has no overrides to rely on. Neither helps an app that grew
|
|
11
|
+
* past its scaffold, which is why the check lives here — on the one path every `dev` and `build` takes.
|
|
12
|
+
*/
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
/**
|
|
16
|
+
* The React this release was tested against, read off the framework's own manifest rather than restated as a
|
|
17
|
+
* constant — the pin and the check cannot drift apart that way. `undefined` if it cannot be read, which only
|
|
18
|
+
* turns the advisory warning off.
|
|
19
|
+
*/
|
|
20
|
+
function testedReactVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const manifest = createRequire(import.meta.url)('../../package.json');
|
|
23
|
+
return manifest.devDependencies?.react;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** The version of an installed package as the *app* resolves it, or `undefined` if it has none. */
|
|
30
|
+
function installedVersion(require, name) {
|
|
31
|
+
try {
|
|
32
|
+
return require(`${name}/package.json`).version;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** `19.2.8` → `19.2`, for comparing minors without pulling in a semver parser. */
|
|
39
|
+
function minor(version) {
|
|
40
|
+
return version.split('.', 2).join('.');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the
|
|
44
|
+
* version this release was tested with.
|
|
45
|
+
*
|
|
46
|
+
* The mismatch is an error because it never works. A different minor is only a warning: upstream declares
|
|
47
|
+
* `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a
|
|
48
|
+
* React release — a worse failure than the one it would prevent.
|
|
49
|
+
*
|
|
50
|
+
* @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the
|
|
51
|
+
* framework's.
|
|
52
|
+
*/
|
|
53
|
+
export function checkReactVersions(rootDir) {
|
|
54
|
+
// Resolved from the project's manifest, so a pnpm layout answers with what the app actually gets.
|
|
55
|
+
const require = createRequire(join(rootDir, 'package.json'));
|
|
56
|
+
const react = installedVersion(require, 'react');
|
|
57
|
+
const reactDom = installedVersion(require, 'react-dom');
|
|
58
|
+
// Missing altogether is the resolver's to report, against the import that needed it and with the path.
|
|
59
|
+
if (!react || !reactDom)
|
|
60
|
+
return;
|
|
61
|
+
if (react !== reactDom) {
|
|
62
|
+
throw new Error(`[rshono] react ${react} and react-dom ${reactDom} resolve to different versions.\n` +
|
|
63
|
+
' React Server Components couple them: the RSC runtime emits a payload the matching react-dom parses, ' +
|
|
64
|
+
'so a split resolution fails inside React while rendering rather than here.\n' +
|
|
65
|
+
' Install both at the same version. If a transitive dependency is what split them, pin them — ' +
|
|
66
|
+
'`overrides` in npm, `pnpm.overrides` in pnpm, `resolutions` in yarn.');
|
|
67
|
+
}
|
|
68
|
+
const tested = testedReactVersion();
|
|
69
|
+
if (tested && minor(tested) !== minor(react)) {
|
|
70
|
+
console.warn(` ⚠ react ${react} is not the ${minor(tested)}.x this rshono was tested against. The RSC runtime is pinned\n` +
|
|
71
|
+
' to an exact version and reaches into React internals, so a different minor can fail at render time.');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=react-versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-versions.js","sourceRoot":"","sources":["../../src/builder/react-versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAEnE,CAAC;QACF,OAAO,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,SAAS,gBAAgB,CAAC,OAAuB,EAAE,IAAY;IAC7D,IAAI,CAAC;QACH,OAAQ,OAAO,CAAC,GAAG,IAAI,eAAe,CAA0B,CAAC,OAAO,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,SAAS,KAAK,CAAC,OAAe;IAC5B,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,kGAAkG;IAClG,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACxD,uGAAuG;IACvG,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;QAAE,OAAO;IAEhC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,kBAAkB,KAAK,kBAAkB,QAAQ,mCAAmC;YAClF,wGAAwG;YACxG,8EAA8E;YAC9E,gGAAgG;YAChG,sEAAsE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,IAAI,CACV,aAAa,KAAK,eAAe,KAAK,CAAC,MAAM,CAAC,gEAAgE;YAC5G,yGAAyG,CAC5G,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["/**\n * The one dependency check the framework makes on an app: that `react` and `react-dom` are the same build.\n *\n * React Server Components couple the two across bundles — `react-server-dom-rspack` reaches into\n * `ReactSharedInternals` and emits a flight payload the *matching* `react-dom` has to parse — so a split\n * resolution is not version skew to be tolerated. It is a crash inside minified React at render time, with\n * nothing in the message pointing at the cause.\n *\n * The monorepo prevents it with `overrides` in `pnpm-workspace.yaml` and `packages/create` pins both exactly\n * for the same reason, because a generated app has no overrides to rely on. Neither helps an app that grew\n * past its scaffold, which is why the check lives here — on the one path every `dev` and `build` takes.\n */\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\n\n/**\n * The React this release was tested against, read off the framework's own manifest rather than restated as a\n * constant — the pin and the check cannot drift apart that way. `undefined` if it cannot be read, which only\n * turns the advisory warning off.\n */\nfunction testedReactVersion(): string | undefined {\n try {\n const manifest = createRequire(import.meta.url)('../../package.json') as {\n devDependencies?: Record<string, string>;\n };\n return manifest.devDependencies?.react;\n } catch {\n return undefined;\n }\n}\n\n/** The version of an installed package as the *app* resolves it, or `undefined` if it has none. */\nfunction installedVersion(require: NodeJS.Require, name: string): string | undefined {\n try {\n return (require(`${name}/package.json`) as { version?: string }).version;\n } catch {\n return undefined;\n }\n}\n\n/** `19.2.8` → `19.2`, for comparing minors without pulling in a semver parser. */\nfunction minor(version: string): string {\n return version.split('.', 2).join('.');\n}\n\n/**\n * Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the\n * version this release was tested with.\n *\n * The mismatch is an error because it never works. A different minor is only a warning: upstream declares\n * `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a\n * React release — a worse failure than the one it would prevent.\n *\n * @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the\n * framework's.\n */\nexport function checkReactVersions(rootDir: string): void {\n // Resolved from the project's manifest, so a pnpm layout answers with what the app actually gets.\n const require = createRequire(join(rootDir, 'package.json'));\n const react = installedVersion(require, 'react');\n const reactDom = installedVersion(require, 'react-dom');\n // Missing altogether is the resolver's to report, against the import that needed it and with the path.\n if (!react || !reactDom) return;\n\n if (react !== reactDom) {\n throw new Error(\n `[rshono] react ${react} and react-dom ${reactDom} resolve to different versions.\\n` +\n ' React Server Components couple them: the RSC runtime emits a payload the matching react-dom parses, ' +\n 'so a split resolution fails inside React while rendering rather than here.\\n' +\n ' Install both at the same version. If a transitive dependency is what split them, pin them — ' +\n '`overrides` in npm, `pnpm.overrides` in pnpm, `resolutions` in yarn.',\n );\n }\n\n const tested = testedReactVersion();\n if (tested && minor(tested) !== minor(react)) {\n console.warn(\n ` ⚠ react ${react} is not the ${minor(tested)}.x this rshono was tested against. The RSC runtime is pinned\\n` +\n ' to an exact version and reaches into React internals, so a different minor can fail at render time.',\n );\n }\n}\n"]}
|
|
@@ -2,18 +2,12 @@ import { type RspackOptions } from '@rspack/core';
|
|
|
2
2
|
import type { RshonoConfig } from '../config.js';
|
|
3
3
|
import type { DeployPreset } from '../deploy/presets.js';
|
|
4
4
|
/**
|
|
5
|
-
* The directory a command writes its bundles to, relative to the project root — one per command,
|
|
6
|
-
*
|
|
5
|
+
* The directory a command writes its bundles to, relative to the project root — one per command, never
|
|
6
|
+
* shared: a `rshono build` alongside a running `rshono dev` would `clean` away the route chunks that
|
|
7
|
+
* server imports lazily, and Rspack's watch-mode emit never re-emits a file it believes it wrote.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the ones the running server worker imports *lazily, at request time*. Every route the worker had
|
|
11
|
-
* not already loaded then fails with `ERR_MODULE_NOT_FOUND`, and no later edit repairs it, because
|
|
12
|
-
* Rspack's watch-mode emit compares against what it believes it already wrote rather than against
|
|
13
|
-
* the disk — so it never re-emits the deleted files. The dev server 500s until it is restarted.
|
|
14
|
-
*
|
|
15
|
-
* Both names are a single level under the root, which {@link ../deploy/filesystem.ts} relies on: it
|
|
16
|
-
* derives the project root from where the bundle ended up, `<out>/server/main.mjs` → `../..`.
|
|
9
|
+
* Both names are a single level under the root, which `deploy/filesystem.ts` relies on to derive the
|
|
10
|
+
* project root from where the bundle ended up.
|
|
17
11
|
*/
|
|
18
12
|
export declare const BUILD_OUT_DIR = "dist";
|
|
19
13
|
export declare const DEV_OUT_DIR = ".rshono";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rspack-config.d.ts","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,aAAa,EAAoB,MAAM,cAAc,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAYzD
|
|
1
|
+
{"version":3,"file":"rspack-config.d.ts","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,aAAa,EAAoB,MAAM,cAAc,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAYzD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,WAAW,YAAY,CAAC;AAqErC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,2IAA2I;IAC3I,MAAM,EAAE,YAAY,CAAC;IACrB,4GAA4G;IAC5G,MAAM,EAAE,YAAY,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAsP1F"}
|