@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
|
@@ -6,31 +6,24 @@ import { basename, dirname, join, win32 } from 'node:path';
|
|
|
6
6
|
import { resolveServerConfig } from '../server/server-config.js';
|
|
7
7
|
import { scanPageFiles } from './page-files.js';
|
|
8
8
|
import { publicEnv } from './public-env.js';
|
|
9
|
-
|
|
10
|
-
//
|
|
9
|
+
import { checkReactVersions } from './react-versions.js';
|
|
10
|
+
// This file lives in `dist/builder/`, so the entries and loaders below are the *built* framework.
|
|
11
11
|
const FRAMEWORK_DIST = join(import.meta.dirname, '..');
|
|
12
12
|
const FRAMEWORK_ROOT = join(FRAMEWORK_DIST, '..');
|
|
13
13
|
const BUNDLED_PACKAGES = /^(@rshono\/core|react|react-dom|react-server-dom-rspack|hono|@hono\/node-server)(\/|$)/;
|
|
14
14
|
/**
|
|
15
|
-
* The directory a command writes its bundles to, relative to the project root — one per command,
|
|
16
|
-
*
|
|
15
|
+
* The directory a command writes its bundles to, relative to the project root — one per command, never
|
|
16
|
+
* shared: a `rshono build` alongside a running `rshono dev` would `clean` away the route chunks that
|
|
17
|
+
* server imports lazily, and Rspack's watch-mode emit never re-emits a file it believes it wrote.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* the ones the running server worker imports *lazily, at request time*. Every route the worker had
|
|
21
|
-
* not already loaded then fails with `ERR_MODULE_NOT_FOUND`, and no later edit repairs it, because
|
|
22
|
-
* Rspack's watch-mode emit compares against what it believes it already wrote rather than against
|
|
23
|
-
* the disk — so it never re-emits the deleted files. The dev server 500s until it is restarted.
|
|
24
|
-
*
|
|
25
|
-
* Both names are a single level under the root, which {@link ../deploy/filesystem.ts} relies on: it
|
|
26
|
-
* derives the project root from where the bundle ended up, `<out>/server/main.mjs` → `../..`.
|
|
19
|
+
* Both names are a single level under the root, which `deploy/filesystem.ts` relies on to derive the
|
|
20
|
+
* project root from where the bundle ended up.
|
|
27
21
|
*/
|
|
28
22
|
export const BUILD_OUT_DIR = 'dist';
|
|
29
23
|
export const DEV_OUT_DIR = '.rshono';
|
|
30
24
|
/**
|
|
31
|
-
* Packages
|
|
32
|
-
*
|
|
33
|
-
* runtime, and those requests resolve from the app's own `src/`.
|
|
25
|
+
* Packages the app's source ends up importing without ever naming them: the RSC transform rewrites a
|
|
26
|
+
* `'use client'` module, a page or an action into imports of the RSC runtime, resolved from the app's `src/`.
|
|
34
27
|
*/
|
|
35
28
|
const INJECTED_PACKAGES = ['react-server-dom-rspack'];
|
|
36
29
|
/** The `node_modules` directory a resolved file sits in — `…/node_modules/pkg/index.js` → `…/node_modules`. */
|
|
@@ -45,17 +38,13 @@ function enclosingNodeModules(file) {
|
|
|
45
38
|
return dir;
|
|
46
39
|
}
|
|
47
40
|
/**
|
|
48
|
-
* Where packages are resolved from: the app's own `node_modules`, then the framework's
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* bun hoist the framework's dependencies into the app's own `node_modules`; pnpm installs them as
|
|
52
|
-
* *siblings* of `@rshono/core` where nothing under the app's tree can see them, and the build then
|
|
53
|
-
* fails with `Can't resolve 'react-server-dom-rspack/client'` in a file the user never wrote that
|
|
54
|
-
* import into.
|
|
41
|
+
* Where packages are resolved from: the app's own `node_modules`, then the framework's — which is what makes
|
|
42
|
+
* {@link INJECTED_PACKAGES} resolvable from app source under pnpm, where the framework's dependencies are
|
|
43
|
+
* installed as siblings of `@rshono/core` rather than hoisted into the app's tree.
|
|
55
44
|
*
|
|
56
|
-
* Asking Node where the framework
|
|
57
|
-
*
|
|
58
|
-
*
|
|
45
|
+
* Asking Node where the framework resolves the package finds it in any layout, and a search path rather than
|
|
46
|
+
* an alias keeps the package's own `exports` conditions in play — the RSC layer, the SSR layer and each
|
|
47
|
+
* deploy target need a different build of it.
|
|
59
48
|
*/
|
|
60
49
|
function resolveModules() {
|
|
61
50
|
const require = createRequire(import.meta.url);
|
|
@@ -70,19 +59,16 @@ function resolveModules() {
|
|
|
70
59
|
// Left to the resolver to report against the request that actually needed it.
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
|
-
// A checkout or a vendored copy, where the framework has real dependencies of its own
|
|
74
|
-
// above found nothing to add.
|
|
62
|
+
// A checkout or a vendored copy, where the framework has real dependencies of its own.
|
|
75
63
|
dirs.add(join(FRAMEWORK_ROOT, 'node_modules'));
|
|
76
64
|
return ['node_modules', ...dirs];
|
|
77
65
|
}
|
|
78
66
|
/**
|
|
79
67
|
* Whether a request names a file rather than a package, and so belongs in the bundle.
|
|
80
68
|
*
|
|
81
|
-
* Rspack's RSC plugins ask for their
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* `ERR_UNSUPPORTED_ESM_URL_SCHEME`. `win32.isAbsolute` also accepts the POSIX form, so it is used on
|
|
85
|
-
* every platform — one code path, and the Windows shapes stay testable off Windows.
|
|
69
|
+
* Rspack's RSC plugins ask for their proxies by absolute path, which on Windows carries a drive letter —
|
|
70
|
+
* externalizing one emits an `import("D:\\…")` Node rejects. `win32.isAbsolute` accepts the POSIX form too,
|
|
71
|
+
* so it runs on every platform and the Windows shapes stay testable off Windows.
|
|
86
72
|
*/
|
|
87
73
|
function isPathRequest(request) {
|
|
88
74
|
return request.startsWith('.') || win32.isAbsolute(request);
|
|
@@ -90,14 +76,11 @@ function isPathRequest(request) {
|
|
|
90
76
|
const BROWSER_TARGETS = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR'];
|
|
91
77
|
const NODE_TARGETS = ['node >= 22'];
|
|
92
78
|
/**
|
|
93
|
-
* Rspack's native CSS pipeline, which both compilers get.
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* adds the loader through the {@link RshonoConfig.rspack} hook, along with the packages a PostCSS
|
|
97
|
-
* pass takes. `postcss` is then a dependency of the apps that want one rather than of every app.
|
|
79
|
+
* Rspack's native CSS pipeline, which both compilers get. It parses *finished* CSS, so a stylesheet needing
|
|
80
|
+
* PostCSS — Tailwind, most obviously — adds that loader through the {@link RshonoConfig.rspack} hook, which
|
|
81
|
+
* keeps `postcss` a dependency of the apps that want one.
|
|
98
82
|
*
|
|
99
|
-
* A fresh object per compiler, so an app
|
|
100
|
-
* changed the other bundle's too.
|
|
83
|
+
* A fresh object per compiler, so an app changing this rule does not silently change the other bundle's.
|
|
101
84
|
*/
|
|
102
85
|
function cssRule() {
|
|
103
86
|
return { test: /\.css$/i, type: 'css/auto' };
|
|
@@ -107,12 +90,22 @@ export function createConfigs(options) {
|
|
|
107
90
|
const srcDir = join(rootDir, 'src');
|
|
108
91
|
const mode = isDev ? 'development' : 'production';
|
|
109
92
|
const outDir = isDev ? DEV_OUT_DIR : BUILD_OUT_DIR;
|
|
93
|
+
// Before anything is compiled: a react/react-dom split fails inside React at render time, and this is the
|
|
94
|
+
// one place that can say so with the two versions in hand.
|
|
95
|
+
checkReactVersions(rootDir);
|
|
110
96
|
const routesFile = ['routes.ts', 'routes.tsx'].map((f) => join(srcDir, f)).find(existsSync);
|
|
111
97
|
if (!routesFile) {
|
|
112
98
|
throw new Error(`[rshono] src/routes.ts not found in ${rootDir} — it is the one required file.`);
|
|
113
99
|
}
|
|
114
100
|
const serverAppFile = ['server.ts', 'server.tsx'].map((f) => join(srcDir, f)).find(existsSync);
|
|
115
101
|
const serverAppAlias = serverAppFile ?? join(FRAMEWORK_DIST, 'runtime', 'empty-server-app.js');
|
|
102
|
+
// Optional, and staying optional — but per-request security is Hono middleware registered there, so an app
|
|
103
|
+
// without one has opted out of all of it, which is worth hearing once rather than discovering. Builds only:
|
|
104
|
+
// `dev` would print it on every rebuild, and it is not news on a developer's machine.
|
|
105
|
+
if (!serverAppFile && !isDev) {
|
|
106
|
+
console.warn(' ⚠ No src/server.ts — this build has no CSRF check and no request body cap. Both are Hono middleware\n' +
|
|
107
|
+
' (`csrf()`, `bodyLimit()`); `npx @rshono/create` scaffolds a src/server.ts with them registered.');
|
|
108
|
+
}
|
|
116
109
|
const rscEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.rsc.js');
|
|
117
110
|
const ssrEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.ssr.js');
|
|
118
111
|
const clientEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.client.js');
|
|
@@ -138,9 +131,8 @@ export function createConfigs(options) {
|
|
|
138
131
|
extensionAlias: { '.js': ['.ts', '.tsx', '.js'] },
|
|
139
132
|
modules: resolveModules(),
|
|
140
133
|
};
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
// one per runtime. Left unset for Node, where the target already implies the `node` condition.
|
|
134
|
+
// Ahead of whatever the Rspack target implies ('...'), which is what hands the server bundle the right
|
|
135
|
+
// build of React and the RSC runtime. Unset for Node, whose target already implies the `node` condition.
|
|
144
136
|
const runtimeConditions = preset.resolveConditions ?? [];
|
|
145
137
|
const serverResolveBase = runtimeConditions.length > 0 ? { ...resolveBase, conditionNames: [...runtimeConditions, '...'] } : resolveBase;
|
|
146
138
|
const rscConditionNames = ['react-server', ...runtimeConditions, '...'];
|
|
@@ -160,6 +152,8 @@ export function createConfigs(options) {
|
|
|
160
152
|
mode,
|
|
161
153
|
target: 'web',
|
|
162
154
|
context: rootDir,
|
|
155
|
+
// Never in a build: a client map is served from `/_static` like everything else beside it, and it would
|
|
156
|
+
// publish the original source of the app's own modules. Dev binds 127.0.0.1 only.
|
|
163
157
|
devtool: isDev ? 'source-map' : false,
|
|
164
158
|
entry: { main: clientEntry },
|
|
165
159
|
output: {
|
|
@@ -194,13 +188,16 @@ export function createConfigs(options) {
|
|
|
194
188
|
mode,
|
|
195
189
|
target: 'node',
|
|
196
190
|
context: rootDir,
|
|
197
|
-
|
|
191
|
+
// In a build too, unlike the client's: the bundle is minified, and without a map every stack trace that
|
|
192
|
+
// reaches `onServerError` — the error-tracker funnel — is unmappable minified frames. A server map is
|
|
193
|
+
// never served to anyone; `dist/server` is not on a public path, and the runtime enables Node's own
|
|
194
|
+
// mapping so no host has to pass a flag.
|
|
195
|
+
devtool: 'source-map',
|
|
198
196
|
entry: { main: rscEntry },
|
|
199
197
|
output: {
|
|
200
198
|
path: join(rootDir, outDir, 'server'),
|
|
201
|
-
// Off in dev
|
|
202
|
-
//
|
|
203
|
-
// `rshono dev` empties the directory on startup, so nothing accumulates across sessions.
|
|
199
|
+
// Off in dev: route chunks are imported lazily, so a superseded one on disk is harmless where deleting
|
|
200
|
+
// one mid-request is not. `rshono dev` empties the directory on startup instead.
|
|
204
201
|
clean: !isDev,
|
|
205
202
|
module: true,
|
|
206
203
|
chunkFormat: 'module',
|
|
@@ -216,14 +213,26 @@ export function createConfigs(options) {
|
|
|
216
213
|
},
|
|
217
214
|
externalsType: 'module-import',
|
|
218
215
|
externals: [
|
|
219
|
-
({ request }, callback) => {
|
|
216
|
+
({ request, contextInfo }, callback) => {
|
|
220
217
|
if (!request ||
|
|
221
218
|
isPathRequest(request) ||
|
|
222
219
|
request.startsWith('@/') ||
|
|
223
220
|
request.startsWith('@rshono/') ||
|
|
224
221
|
request.startsWith('builtin:') ||
|
|
225
222
|
request.includes('!') ||
|
|
226
|
-
BUNDLED_PACKAGES.test(request)
|
|
223
|
+
BUNDLED_PACKAGES.test(request) ||
|
|
224
|
+
// Anything reached from the SSR layer, which is where `'use client'` components are rendered on the
|
|
225
|
+
// server. It has to be *compiled* rather than imported by name, because the env-shadow loader is what
|
|
226
|
+
// keeps a secret out of SSR'd HTML and a loader cannot run on a module the bundle only names — an
|
|
227
|
+
// externalized third-party client component is loaded raw at request time and reads the real
|
|
228
|
+
// `process.env`. Widening the loader's rule to cover `node_modules` did not reach this: there was no
|
|
229
|
+
// module for it to run on.
|
|
230
|
+
//
|
|
231
|
+
// Free of the usual bundling trade-off, too. Every module in this layer is in the *browser* bundle as
|
|
232
|
+
// well, so it is already required to be bundleable — a native addon or a `__dirname` file read could
|
|
233
|
+
// not have been a client component in the first place. The RSC layer, where server-only dependencies
|
|
234
|
+
// live, keeps the externals policy.
|
|
235
|
+
contextInfo?.issuerLayer === Layers.ssr) {
|
|
227
236
|
return callback();
|
|
228
237
|
}
|
|
229
238
|
callback(undefined, `module-import ${request}`);
|
|
@@ -234,8 +243,7 @@ export function createConfigs(options) {
|
|
|
234
243
|
alias: {
|
|
235
244
|
'@rshono/routes$': routesFile,
|
|
236
245
|
'@rshono/server-app$': serverAppAlias,
|
|
237
|
-
//
|
|
238
|
-
// preset can declare a POSIX-looking path and still resolve on Windows.
|
|
246
|
+
// Split on '/' so a preset can declare a POSIX-looking path and still resolve on Windows.
|
|
239
247
|
'@rshono/deploy$': join(FRAMEWORK_DIST, ...preset.runtimeModule.split('/')),
|
|
240
248
|
'@': srcDir,
|
|
241
249
|
},
|
|
@@ -248,13 +256,24 @@ export function createConfigs(options) {
|
|
|
248
256
|
use: [{ loader: join(FRAMEWORK_DIST, 'builder', 'page-entry-loader.cjs') }],
|
|
249
257
|
},
|
|
250
258
|
{
|
|
259
|
+
// Deliberately not scoped to `srcDir`: a `'use client'` component from `node_modules` is SSR'd in
|
|
260
|
+
// the same layer, and scoping this to the app's own source left those rendering against the real
|
|
261
|
+
// `process.env` while the browser bundle saw the `PUBLIC_`-only view — a hydration mismatch on
|
|
262
|
+
// anything the host sets, and a leak for anything secret. The loader's own layer check is what
|
|
263
|
+
// decides; every other module gets one `includes('process.env')` scan.
|
|
251
264
|
test: /\.[cm]?[tj]sx?$/,
|
|
252
|
-
include: srcDir,
|
|
253
265
|
enforce: 'pre',
|
|
254
266
|
use: [
|
|
255
267
|
{
|
|
256
268
|
loader: join(FRAMEWORK_DIST, 'builder', 'env-shadow-loader.cjs'),
|
|
257
|
-
|
|
269
|
+
// `Object.create` over the real `process`, not a bare `{ env }`: the prelude shadows the whole
|
|
270
|
+
// binding for that module, and `react-dom/server` is in this layer too — anything reading
|
|
271
|
+
// `process.nextTick` or `process.platform` has to still find it. Not a `{ __proto__: … }`
|
|
272
|
+
// literal, whose meaning would change if a minifier ever quoted the key.
|
|
273
|
+
options: {
|
|
274
|
+
prelude: `const process = Object.assign(Object.create(globalThis.process ?? Object.prototype), { env: ${JSON.stringify(publicEnv(isDev))} }); `,
|
|
275
|
+
layer: Layers.ssr,
|
|
276
|
+
},
|
|
258
277
|
},
|
|
259
278
|
],
|
|
260
279
|
},
|
|
@@ -286,8 +305,7 @@ export function createConfigs(options) {
|
|
|
286
305
|
],
|
|
287
306
|
performance: false,
|
|
288
307
|
};
|
|
289
|
-
// The platform's
|
|
290
|
-
// preset decided.
|
|
308
|
+
// The platform's overrides first, then the user's hook — so an app can adjust whatever a preset decided.
|
|
291
309
|
preset.configureServer?.(serverConfig);
|
|
292
310
|
const rspackHook = config.rspack;
|
|
293
311
|
if (rspackHook) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rspack-config.js","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAuD,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAG3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,kGAAkG;AAClG,kGAAkG;AAClG,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACvD,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;AAElD,MAAM,gBAAgB,GAAG,wFAAwF,CAAC;AAElH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEtD,+GAA+G;AAC/G,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,cAAc,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,cAAc;IACrB,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACxD,IAAI,GAAG;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,8EAA8E;QAChF,CAAC;IACH,CAAC;IACD,qGAAqG;IACrG,8BAA8B;IAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AACjF,MAAM,YAAY,GAAG,CAAC,YAAY,CAAC,CAAC;AAEpC;;;;;;;;;GASG;AACH,SAAS,OAAO;IACd,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC/C,CAAC;AAYD,MAAM,UAAU,aAAa,CAAC,OAA4B;IACxD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,EAAE,GAAG,OAAO,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;IAEnD,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5F,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,iCAAiC,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,aAAa,IAAI,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAE/F,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IACjE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,CAAC,OAAiB,EAAe,EAAE,CAAC,CAAC;QACnD,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,mBAAmB;QAC5B,GAAG,EAAE;YACH,MAAM,EAAE,oBAAoB;YAC5B,OAAO,EAAE;gBACP,YAAY,EAAE,MAAM;gBACpB,GAAG,EAAE;oBACH,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;oBAClE,YAAY,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE;iBAC7C;gBACD,GAAG,EAAE,EAAE,OAAO,EAAE;gBAChB,iBAAiB,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE;aACnD;SACF;QACD,IAAI,EAAE,iBAAiB;KACxB,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG;QAClB,UAAU,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC;QACnD,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QACjD,OAAO,EAAE,cAAc,EAAE;KAC1B,CAAC;IAEF,mGAAmG;IACnG,mGAAmG;IACnG,+FAA+F;IAC/F,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACzD,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,EAAE,cAAc,EAAE,CAAC,GAAG,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACzI,MAAM,iBAAiB,GAAG,CAAC,cAAc,EAAE,GAAG,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAExE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC9E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;IAE1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG;QACrB,KAAK,CAAC,QAAkB;YACtB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YACnE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;YAC1D,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;KACF,CAAC;IAEF,MAAM,YAAY,GAAkB;QAClC,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK;QACrC,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC5B,MAAM,EAAE;YACN,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC;YACrC,UAAU,EAAE,WAAW;YACvB,KAAK,EAAE,CAAC,KAAK;YACb,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,8BAA8B;YACnE,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,gCAAgC;YAC5E,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iCAAiC;YAC5E,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iCAAiC;YACjF,mBAAmB,EAAE,2BAA2B;SACjD;QACD,YAAY,EAAE;YACZ,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;SACtC;QACD,OAAO,EAAE;YACP,GAAG,WAAW;YACd,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;SACvB;QACD,MAAM,EAAE;YACN,KAAK,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,sDAAsD,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;SAC9H;QACD,OAAO,EAAE;YACP,IAAI,YAAY,EAAE;YAClB,IAAI,MAAM,CAAC,YAAY,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5E,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,0BAA0B,EAAE,EAAE,IAAI,wBAAwB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5F;QACD,WAAW,EAAE,KAAK;KACnB,CAAC;IAEF,MAAM,YAAY,GAAkB;QAClC,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK;QACrC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,MAAM,EAAE;YACN,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC;YACrC,+FAA+F;YAC/F,+FAA+F;YAC/F,yFAAyF;YACzF,KAAK,EAAE,CAAC,KAAK;YACb,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,QAAQ;YACrB,YAAY,EAAE,QAAQ;YACtB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC3B,QAAQ,EAAE,UAAU;YACpB,aAAa,EAAE,mBAAmB;YAClC,UAAU,EAAE,WAAW;YACvB,mBAAmB,EAAE,2BAA2B;SACjD;QACD,YAAY,EAAE;YACZ,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;SAC/B;QACD,aAAa,EAAE,eAAe;QAC9B,SAAS,EAAE;YACT,CAAC,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE;gBACxB,IACE,CAAC,OAAO;oBACR,aAAa,CAAC,OAAO,CAAC;oBACtB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;oBACxB,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;oBAC9B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;oBAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;oBACrB,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAC9B,CAAC;oBACD,OAAO,QAAQ,EAAE,CAAC;gBACpB,CAAC;gBACD,QAAQ,CAAC,SAAS,EAAE,iBAAiB,OAAO,EAAE,CAAC,CAAC;YAClD,CAAC;SACF;QACD,OAAO,EAAE;YACP,GAAG,iBAAiB;YACpB,KAAK,EAAE;gBACL,iBAAiB,EAAE,UAAU;gBAC7B,qBAAqB,EAAE,cAAc;gBACrC,2FAA2F;gBAC3F,wEAAwE;gBACxE,iBAAiB,EAAE,IAAI,CAAC,cAAc,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC3E,GAAG,EAAE,MAAM;aACZ;SACF;QACD,MAAM,EAAE;YACN,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACnD,OAAO,EAAE,KAAK;oBACd,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,uBAAuB,CAAC,EAAE,CAAC;iBAC5E;gBACD;oBACE,IAAI,EAAE,iBAAiB;oBACvB,OAAO,EAAE,MAAM;oBACf,OAAO,EAAE,KAAK;oBACd,GAAG,EAAE;wBACH;4BACE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,uBAAuB,CAAC;4BAChE,OAAO,EAAE,EAAE,OAAO,EAAE,0BAA0B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE;yBAC1G;qBACF;iBACF;gBACD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,YAAY,CAAC,CAAC,CAAC;gBACpD,OAAO,EAAE;gBACT;oBACE,IAAI,EAAE,sDAAsD;oBAC5D,IAAI,EAAE,OAAO;oBACb,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;iBAC3B;gBACD,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE;gBACzC;oBACE,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,MAAM,CAAC,GAAG;oBACjB,OAAO,EAAE,EAAE,cAAc,EAAE,iBAAiB,EAAE;iBAC/C;gBACD;oBACE,WAAW,EAAE,MAAM,CAAC,GAAG;oBACvB,OAAO,EAAE,QAAQ;oBACjB,OAAO,EAAE,EAAE,cAAc,EAAE,iBAAiB,EAAE;iBAC/C;aACF;SACF;QACD,OAAO,EAAE;YACP,cAAc;YACd,IAAI,YAAY,CAAC,EAAE,wBAAwB,EAAE,CAAC;YAC9C,4FAA4F;YAC5F,IAAI,MAAM,CAAC,YAAY,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;SAC/G;QACD,WAAW,EAAE,KAAK;KACnB,CAAC;IAEF,6FAA6F;IAC7F,kBAAkB;IAClB,MAAM,CAAC,eAAe,EAAE,CAAC,YAAY,CAAC,CAAC;IAEvC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,IAAI,UAAU,EAAE,CAAC;QACf,OAAO;YACL,UAAU,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,IAAI,YAAY;YACpE,UAAU,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,YAAY;SACpE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { rspack, type Compiler, type RspackOptions, type RuleSetRule } from '@rspack/core';\nimport { ReactRefreshRspackPlugin } from '@rspack/plugin-react-refresh';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, win32 } from 'node:path';\nimport type { RshonoConfig } from '../config.js';\nimport type { DeployPreset } from '../deploy/presets.js';\nimport { resolveServerConfig } from '../server/server-config.js';\nimport { scanPageFiles } from './page-files.js';\nimport { publicEnv } from './public-env.js';\n\n// The framework's own compiled output (this file lives in `dist/builder/`), which is what the two\n// compilers consume: the entries and loaders below are the *built* framework, not its TypeScript.\nconst FRAMEWORK_DIST = join(import.meta.dirname, '..');\nconst FRAMEWORK_ROOT = join(FRAMEWORK_DIST, '..');\n\nconst BUNDLED_PACKAGES = /^(@rshono\\/core|react|react-dom|react-server-dom-rspack|hono|@hono\\/node-server)(\\/|$)/;\n\n/**\n * The directory a command writes its bundles to, relative to the project root — one per command,\n * never shared.\n *\n * `rshono build` run while `rshono dev` is up would otherwise write over the dev server's own\n * output: the build's `clean` empties `<out>/server`, and the route chunks it deletes are exactly\n * the ones the running server worker imports *lazily, at request time*. Every route the worker had\n * not already loaded then fails with `ERR_MODULE_NOT_FOUND`, and no later edit repairs it, because\n * Rspack's watch-mode emit compares against what it believes it already wrote rather than against\n * the disk — so it never re-emits the deleted files. The dev server 500s until it is restarted.\n *\n * Both names are a single level under the root, which {@link ../deploy/filesystem.ts} relies on: it\n * derives the project root from where the bundle ended up, `<out>/server/main.mjs` → `../..`.\n */\nexport const BUILD_OUT_DIR = 'dist';\nexport const DEV_OUT_DIR = '.rshono';\n\n/**\n * Packages that end up imported *by app source* without the app ever mentioning them: the RSC\n * transform rewrites a `'use client'` module, a page or a server action into imports of the RSC\n * runtime, and those requests resolve from the app's own `src/`.\n */\nconst INJECTED_PACKAGES = ['react-server-dom-rspack'];\n\n/** The `node_modules` directory a resolved file sits in — `…/node_modules/pkg/index.js` → `…/node_modules`. */\nfunction enclosingNodeModules(file: string): string | undefined {\n let dir = dirname(file);\n while (basename(dir) !== 'node_modules') {\n const parent = dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n return dir;\n}\n\n/**\n * Where packages are resolved from: the app's own `node_modules`, then the framework's.\n *\n * The second part is what makes {@link INJECTED_PACKAGES} resolvable from app source. npm, yarn and\n * bun hoist the framework's dependencies into the app's own `node_modules`; pnpm installs them as\n * *siblings* of `@rshono/core` where nothing under the app's tree can see them, and the build then\n * fails with `Can't resolve 'react-server-dom-rspack/client'` in a file the user never wrote that\n * import into.\n *\n * Asking Node where the framework itself resolves the package finds the directory in any layout, and\n * a search path rather than an alias keeps the package's own `exports` conditions in play — the RSC\n * layer, the SSR layer and each deploy target need a different build of it.\n */\nfunction resolveModules(): string[] {\n const require = createRequire(import.meta.url);\n const dirs = new Set<string>();\n for (const name of INJECTED_PACKAGES) {\n try {\n const dir = enclosingNodeModules(require.resolve(name));\n if (dir) dirs.add(dir);\n } catch {\n // Left to the resolver to report against the request that actually needed it.\n }\n }\n // A checkout or a vendored copy, where the framework has real dependencies of its own and the lookup\n // above found nothing to add.\n dirs.add(join(FRAMEWORK_ROOT, 'node_modules'));\n return ['node_modules', ...dirs];\n}\n\n/**\n * Whether a request names a file rather than a package, and so belongs in the bundle.\n *\n * Rspack's RSC plugins ask for their client and server-entry proxies by *absolute path*, which on\n * Windows means a drive letter (`D:\\app\\src\\home.tsx`) instead of a leading slash. Externalizing one\n * of those emits `import(\"D:\\\\app\\\\src\\\\home.tsx\")`, which Node rejects with\n * `ERR_UNSUPPORTED_ESM_URL_SCHEME`. `win32.isAbsolute` also accepts the POSIX form, so it is used on\n * every platform — one code path, and the Windows shapes stay testable off Windows.\n */\nfunction isPathRequest(request: string): boolean {\n return request.startsWith('.') || win32.isAbsolute(request);\n}\n\nconst BROWSER_TARGETS = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR'];\nconst NODE_TARGETS = ['node >= 22'];\n\n/**\n * Rspack's native CSS pipeline, which both compilers get.\n *\n * It parses *finished* CSS, so a stylesheet needing a PostCSS plugin — Tailwind, most obviously —\n * adds the loader through the {@link RshonoConfig.rspack} hook, along with the packages a PostCSS\n * pass takes. `postcss` is then a dependency of the apps that want one rather than of every app.\n *\n * A fresh object per compiler, so an app that reaches in to change this rule does not find it has\n * changed the other bundle's too.\n */\nfunction cssRule(): RuleSetRule {\n return { test: /\\.css$/i, type: 'css/auto' };\n}\n\nexport interface RspackConfigOptions {\n rootDir: string;\n isDev: boolean;\n /** The project's resolved config — supplies the {@link RshonoConfig.rspack} hook and the runtime settings baked into the server bundle. */\n config: RshonoConfig;\n /** The platform being built for: decides the `@rshono/deploy` runtime and any server-compiler overrides. */\n preset: DeployPreset;\n onServerComponentChanges?: () => void;\n}\n\nexport function createConfigs(options: RspackConfigOptions): [RspackOptions, RspackOptions] {\n const { rootDir, isDev, config, preset, onServerComponentChanges } = options;\n const srcDir = join(rootDir, 'src');\n const mode = isDev ? 'development' : 'production';\n const outDir = isDev ? DEV_OUT_DIR : BUILD_OUT_DIR;\n\n const routesFile = ['routes.ts', 'routes.tsx'].map((f) => join(srcDir, f)).find(existsSync);\n if (!routesFile) {\n throw new Error(`[rshono] src/routes.ts not found in ${rootDir} — it is the one required file.`);\n }\n const serverAppFile = ['server.ts', 'server.tsx'].map((f) => join(srcDir, f)).find(existsSync);\n const serverAppAlias = serverAppFile ?? join(FRAMEWORK_DIST, 'runtime', 'empty-server-app.js');\n\n const rscEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.rsc.js');\n const ssrEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.ssr.js');\n const clientEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.client.js');\n\n const swcRule = (targets: string[]): RuleSetRule => ({\n test: /\\.[cm]?[jt]sx?$/,\n exclude: /[\\\\/]core-js[\\\\/]/,\n use: {\n loader: 'builtin:swc-loader',\n options: {\n detectSyntax: 'auto',\n jsc: {\n transform: { react: { runtime: 'automatic', development: isDev } },\n experimental: { keepImportAttributes: true },\n },\n env: { targets },\n rspackExperiments: { reactServerComponents: true },\n },\n },\n type: 'javascript/auto',\n });\n\n const resolveBase = {\n extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],\n extensionAlias: { '.js': ['.ts', '.tsx', '.js'] },\n modules: resolveModules(),\n };\n\n // The platform's own resolve conditions, ahead of whatever the Rspack target implies ('...'). This\n // is what hands the server bundle the right build of React and the RSC runtime, both of which ship\n // one per runtime. Left unset for Node, where the target already implies the `node` condition.\n const runtimeConditions = preset.resolveConditions ?? [];\n const serverResolveBase = runtimeConditions.length > 0 ? { ...resolveBase, conditionNames: [...runtimeConditions, '...'] } : resolveBase;\n const rscConditionNames = ['react-server', ...runtimeConditions, '...'];\n\n const { ServerPlugin, ClientPlugin } = rspack.experiments.rsc.createPlugins();\n const { Layers } = rspack.experiments.rsc;\n\n const pageFiles = new Set<string>();\n scanPageFiles(routesFile, srcDir, pageFiles);\n const pageScanPlugin = {\n apply(compiler: Compiler) {\n const refresh = () => scanPageFiles(routesFile, srcDir, pageFiles);\n compiler.hooks.beforeRun.tap('rshono/page-scan', refresh);\n compiler.hooks.watchRun.tap('rshono/page-scan', refresh);\n },\n };\n\n const clientConfig: RspackOptions = {\n name: 'client',\n mode,\n target: 'web',\n context: rootDir,\n devtool: isDev ? 'source-map' : false,\n entry: { main: clientEntry },\n output: {\n path: join(rootDir, outDir, 'static'),\n publicPath: '/_static/',\n clean: !isDev,\n filename: isDev ? 'chunks/main.js' : 'chunks/main.[contenthash].js',\n chunkFilename: isDev ? 'chunks/[name].js' : 'chunks/[name].[contenthash].js',\n cssFilename: isDev ? 'chunks/[name].css' : 'chunks/[name].[contenthash].css',\n cssChunkFilename: isDev ? 'chunks/[name].css' : 'chunks/[name].[contenthash].css',\n assetModuleFilename: 'assets/[name].[hash][ext]',\n },\n optimization: {\n moduleIds: isDev ? 'named' : 'hashed',\n },\n resolve: {\n ...resolveBase,\n alias: { '@': srcDir },\n },\n module: {\n rules: [swcRule(BROWSER_TARGETS), cssRule(), { test: /\\.(png|jpe?g|gif|webp|avif|ico|svg|woff2?|ttf|otf)$/i, type: 'asset' }],\n },\n plugins: [\n new ClientPlugin(),\n new rspack.DefinePlugin({ 'process.env': JSON.stringify(publicEnv(isDev)) }),\n ...(isDev ? [new rspack.HotModuleReplacementPlugin(), new ReactRefreshRspackPlugin()] : []),\n ],\n performance: false,\n };\n\n const serverConfig: RspackOptions = {\n name: 'server',\n mode,\n target: 'node',\n context: rootDir,\n devtool: isDev ? 'source-map' : false,\n entry: { main: rscEntry },\n output: {\n path: join(rootDir, outDir, 'server'),\n // Off in dev, matching the client compiler above: route chunks are imported lazily, at request\n // time, so leaving a superseded one on disk is harmless where deleting one mid-request is not.\n // `rshono dev` empties the directory on startup, so nothing accumulates across sessions.\n clean: !isDev,\n module: true,\n chunkFormat: 'module',\n chunkLoading: 'import',\n library: { type: 'module' },\n filename: 'main.mjs',\n chunkFilename: 'chunks/[name].mjs',\n publicPath: '/_static/',\n assetModuleFilename: 'assets/[name].[hash][ext]',\n },\n optimization: {\n minimize: isDev ? false : true,\n },\n externalsType: 'module-import',\n externals: [\n ({ request }, callback) => {\n if (\n !request ||\n isPathRequest(request) ||\n request.startsWith('@/') ||\n request.startsWith('@rshono/') ||\n request.startsWith('builtin:') ||\n request.includes('!') ||\n BUNDLED_PACKAGES.test(request)\n ) {\n return callback();\n }\n callback(undefined, `module-import ${request}`);\n },\n ],\n resolve: {\n ...serverResolveBase,\n alias: {\n '@rshono/routes$': routesFile,\n '@rshono/server-app$': serverAppAlias,\n // The one import that decides which platform the server bundle is for. Split on '/' so the\n // preset can declare a POSIX-looking path and still resolve on Windows.\n '@rshono/deploy$': join(FRAMEWORK_DIST, ...preset.runtimeModule.split('/')),\n '@': srcDir,\n },\n },\n module: {\n rules: [\n {\n test: (resource: string) => pageFiles.has(resource),\n enforce: 'pre',\n use: [{ loader: join(FRAMEWORK_DIST, 'builder', 'page-entry-loader.cjs') }],\n },\n {\n test: /\\.[cm]?[tj]sx?$/,\n include: srcDir,\n enforce: 'pre',\n use: [\n {\n loader: join(FRAMEWORK_DIST, 'builder', 'env-shadow-loader.cjs'),\n options: { prelude: `const process = { env: ${JSON.stringify(publicEnv(isDev))} }; `, layer: Layers.ssr },\n },\n ],\n },\n swcRule([...(preset.syntaxTargets ?? NODE_TARGETS)]),\n cssRule(),\n {\n test: /\\.(png|jpe?g|gif|webp|avif|ico|svg|woff2?|ttf|otf)$/i,\n type: 'asset',\n generator: { emit: false },\n },\n { resource: ssrEntry, layer: Layers.ssr },\n {\n resource: rscEntry,\n layer: Layers.rsc,\n resolve: { conditionNames: rscConditionNames },\n },\n {\n issuerLayer: Layers.rsc,\n exclude: ssrEntry,\n resolve: { conditionNames: rscConditionNames },\n },\n ],\n },\n plugins: [\n pageScanPlugin,\n new ServerPlugin({ onServerComponentChanges }),\n // Bakes rshono.config.ts into the bundle, read back as `__RSHONO_CONFIG__` at request time.\n new rspack.DefinePlugin({ __RSHONO_CONFIG__: JSON.stringify(resolveServerConfig(config, { isDev, outDir })) }),\n ],\n performance: false,\n };\n\n // The platform's own overrides, then the user's hook — so an app can still adjust whatever a\n // preset decided.\n preset.configureServer?.(serverConfig);\n\n const rspackHook = config.rspack;\n if (rspackHook) {\n return [\n rspackHook(clientConfig, { isServer: false, isDev }) ?? clientConfig,\n rspackHook(serverConfig, { isServer: true, isDev }) ?? serverConfig,\n ];\n }\n return [clientConfig, serverConfig];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rspack-config.js","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { rspack, type Compiler, type RspackOptions, type RuleSetRule } from '@rspack/core';\nimport { ReactRefreshRspackPlugin } from '@rspack/plugin-react-refresh';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, win32 } from 'node:path';\nimport type { RshonoConfig } from '../config.js';\nimport type { DeployPreset } from '../deploy/presets.js';\nimport { resolveServerConfig } from '../server/server-config.js';\nimport { scanPageFiles } from './page-files.js';\nimport { publicEnv } from './public-env.js';\nimport { checkReactVersions } from './react-versions.js';\n\n// This file lives in `dist/builder/`, so the entries and loaders below are the *built* framework.\nconst FRAMEWORK_DIST = join(import.meta.dirname, '..');\nconst FRAMEWORK_ROOT = join(FRAMEWORK_DIST, '..');\n\nconst BUNDLED_PACKAGES = /^(@rshono\\/core|react|react-dom|react-server-dom-rspack|hono|@hono\\/node-server)(\\/|$)/;\n\n/**\n * The directory a command writes its bundles to, relative to the project root — one per command, never\n * shared: a `rshono build` alongside a running `rshono dev` would `clean` away the route chunks that\n * server imports lazily, and Rspack's watch-mode emit never re-emits a file it believes it wrote.\n *\n * Both names are a single level under the root, which `deploy/filesystem.ts` relies on to derive the\n * project root from where the bundle ended up.\n */\nexport const BUILD_OUT_DIR = 'dist';\nexport const DEV_OUT_DIR = '.rshono';\n\n/**\n * Packages the app's source ends up importing without ever naming them: the RSC transform rewrites a\n * `'use client'` module, a page or an action into imports of the RSC runtime, resolved from the app's `src/`.\n */\nconst INJECTED_PACKAGES = ['react-server-dom-rspack'];\n\n/** The `node_modules` directory a resolved file sits in — `…/node_modules/pkg/index.js` → `…/node_modules`. */\nfunction enclosingNodeModules(file: string): string | undefined {\n let dir = dirname(file);\n while (basename(dir) !== 'node_modules') {\n const parent = dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n return dir;\n}\n\n/**\n * Where packages are resolved from: the app's own `node_modules`, then the framework's — which is what makes\n * {@link INJECTED_PACKAGES} resolvable from app source under pnpm, where the framework's dependencies are\n * installed as siblings of `@rshono/core` rather than hoisted into the app's tree.\n *\n * Asking Node where the framework resolves the package finds it in any layout, and a search path rather than\n * an alias keeps the package's own `exports` conditions in play — the RSC layer, the SSR layer and each\n * deploy target need a different build of it.\n */\nfunction resolveModules(): string[] {\n const require = createRequire(import.meta.url);\n const dirs = new Set<string>();\n for (const name of INJECTED_PACKAGES) {\n try {\n const dir = enclosingNodeModules(require.resolve(name));\n if (dir) dirs.add(dir);\n } catch {\n // Left to the resolver to report against the request that actually needed it.\n }\n }\n // A checkout or a vendored copy, where the framework has real dependencies of its own.\n dirs.add(join(FRAMEWORK_ROOT, 'node_modules'));\n return ['node_modules', ...dirs];\n}\n\n/**\n * Whether a request names a file rather than a package, and so belongs in the bundle.\n *\n * Rspack's RSC plugins ask for their proxies by absolute path, which on Windows carries a drive letter —\n * externalizing one emits an `import(\"D:\\\\…\")` Node rejects. `win32.isAbsolute` accepts the POSIX form too,\n * so it runs on every platform and the Windows shapes stay testable off Windows.\n */\nfunction isPathRequest(request: string): boolean {\n return request.startsWith('.') || win32.isAbsolute(request);\n}\n\nconst BROWSER_TARGETS = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR'];\nconst NODE_TARGETS = ['node >= 22'];\n\n/**\n * Rspack's native CSS pipeline, which both compilers get. It parses *finished* CSS, so a stylesheet needing\n * PostCSS — Tailwind, most obviously — adds that loader through the {@link RshonoConfig.rspack} hook, which\n * keeps `postcss` a dependency of the apps that want one.\n *\n * A fresh object per compiler, so an app changing this rule does not silently change the other bundle's.\n */\nfunction cssRule(): RuleSetRule {\n return { test: /\\.css$/i, type: 'css/auto' };\n}\n\nexport interface RspackConfigOptions {\n rootDir: string;\n isDev: boolean;\n /** The project's resolved config — supplies the {@link RshonoConfig.rspack} hook and the runtime settings baked into the server bundle. */\n config: RshonoConfig;\n /** The platform being built for: decides the `@rshono/deploy` runtime and any server-compiler overrides. */\n preset: DeployPreset;\n onServerComponentChanges?: () => void;\n}\n\nexport function createConfigs(options: RspackConfigOptions): [RspackOptions, RspackOptions] {\n const { rootDir, isDev, config, preset, onServerComponentChanges } = options;\n const srcDir = join(rootDir, 'src');\n const mode = isDev ? 'development' : 'production';\n const outDir = isDev ? DEV_OUT_DIR : BUILD_OUT_DIR;\n\n // Before anything is compiled: a react/react-dom split fails inside React at render time, and this is the\n // one place that can say so with the two versions in hand.\n checkReactVersions(rootDir);\n\n const routesFile = ['routes.ts', 'routes.tsx'].map((f) => join(srcDir, f)).find(existsSync);\n if (!routesFile) {\n throw new Error(`[rshono] src/routes.ts not found in ${rootDir} — it is the one required file.`);\n }\n const serverAppFile = ['server.ts', 'server.tsx'].map((f) => join(srcDir, f)).find(existsSync);\n const serverAppAlias = serverAppFile ?? join(FRAMEWORK_DIST, 'runtime', 'empty-server-app.js');\n // Optional, and staying optional — but per-request security is Hono middleware registered there, so an app\n // without one has opted out of all of it, which is worth hearing once rather than discovering. Builds only:\n // `dev` would print it on every rebuild, and it is not news on a developer's machine.\n if (!serverAppFile && !isDev) {\n console.warn(\n ' ⚠ No src/server.ts — this build has no CSRF check and no request body cap. Both are Hono middleware\\n' +\n ' (`csrf()`, `bodyLimit()`); `npx @rshono/create` scaffolds a src/server.ts with them registered.',\n );\n }\n\n const rscEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.rsc.js');\n const ssrEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.ssr.js');\n const clientEntry = join(FRAMEWORK_DIST, 'runtime', 'entry.client.js');\n\n const swcRule = (targets: string[]): RuleSetRule => ({\n test: /\\.[cm]?[jt]sx?$/,\n exclude: /[\\\\/]core-js[\\\\/]/,\n use: {\n loader: 'builtin:swc-loader',\n options: {\n detectSyntax: 'auto',\n jsc: {\n transform: { react: { runtime: 'automatic', development: isDev } },\n experimental: { keepImportAttributes: true },\n },\n env: { targets },\n rspackExperiments: { reactServerComponents: true },\n },\n },\n type: 'javascript/auto',\n });\n\n const resolveBase = {\n extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],\n extensionAlias: { '.js': ['.ts', '.tsx', '.js'] },\n modules: resolveModules(),\n };\n\n // Ahead of whatever the Rspack target implies ('...'), which is what hands the server bundle the right\n // build of React and the RSC runtime. Unset for Node, whose target already implies the `node` condition.\n const runtimeConditions = preset.resolveConditions ?? [];\n const serverResolveBase = runtimeConditions.length > 0 ? { ...resolveBase, conditionNames: [...runtimeConditions, '...'] } : resolveBase;\n const rscConditionNames = ['react-server', ...runtimeConditions, '...'];\n\n const { ServerPlugin, ClientPlugin } = rspack.experiments.rsc.createPlugins();\n const { Layers } = rspack.experiments.rsc;\n\n const pageFiles = new Set<string>();\n scanPageFiles(routesFile, srcDir, pageFiles);\n const pageScanPlugin = {\n apply(compiler: Compiler) {\n const refresh = () => scanPageFiles(routesFile, srcDir, pageFiles);\n compiler.hooks.beforeRun.tap('rshono/page-scan', refresh);\n compiler.hooks.watchRun.tap('rshono/page-scan', refresh);\n },\n };\n\n const clientConfig: RspackOptions = {\n name: 'client',\n mode,\n target: 'web',\n context: rootDir,\n // Never in a build: a client map is served from `/_static` like everything else beside it, and it would\n // publish the original source of the app's own modules. Dev binds 127.0.0.1 only.\n devtool: isDev ? 'source-map' : false,\n entry: { main: clientEntry },\n output: {\n path: join(rootDir, outDir, 'static'),\n publicPath: '/_static/',\n clean: !isDev,\n filename: isDev ? 'chunks/main.js' : 'chunks/main.[contenthash].js',\n chunkFilename: isDev ? 'chunks/[name].js' : 'chunks/[name].[contenthash].js',\n cssFilename: isDev ? 'chunks/[name].css' : 'chunks/[name].[contenthash].css',\n cssChunkFilename: isDev ? 'chunks/[name].css' : 'chunks/[name].[contenthash].css',\n assetModuleFilename: 'assets/[name].[hash][ext]',\n },\n optimization: {\n moduleIds: isDev ? 'named' : 'hashed',\n },\n resolve: {\n ...resolveBase,\n alias: { '@': srcDir },\n },\n module: {\n rules: [swcRule(BROWSER_TARGETS), cssRule(), { test: /\\.(png|jpe?g|gif|webp|avif|ico|svg|woff2?|ttf|otf)$/i, type: 'asset' }],\n },\n plugins: [\n new ClientPlugin(),\n new rspack.DefinePlugin({ 'process.env': JSON.stringify(publicEnv(isDev)) }),\n ...(isDev ? [new rspack.HotModuleReplacementPlugin(), new ReactRefreshRspackPlugin()] : []),\n ],\n performance: false,\n };\n\n const serverConfig: RspackOptions = {\n name: 'server',\n mode,\n target: 'node',\n context: rootDir,\n // In a build too, unlike the client's: the bundle is minified, and without a map every stack trace that\n // reaches `onServerError` — the error-tracker funnel — is unmappable minified frames. A server map is\n // never served to anyone; `dist/server` is not on a public path, and the runtime enables Node's own\n // mapping so no host has to pass a flag.\n devtool: 'source-map',\n entry: { main: rscEntry },\n output: {\n path: join(rootDir, outDir, 'server'),\n // Off in dev: route chunks are imported lazily, so a superseded one on disk is harmless where deleting\n // one mid-request is not. `rshono dev` empties the directory on startup instead.\n clean: !isDev,\n module: true,\n chunkFormat: 'module',\n chunkLoading: 'import',\n library: { type: 'module' },\n filename: 'main.mjs',\n chunkFilename: 'chunks/[name].mjs',\n publicPath: '/_static/',\n assetModuleFilename: 'assets/[name].[hash][ext]',\n },\n optimization: {\n minimize: isDev ? false : true,\n },\n externalsType: 'module-import',\n externals: [\n ({ request, contextInfo }, callback) => {\n if (\n !request ||\n isPathRequest(request) ||\n request.startsWith('@/') ||\n request.startsWith('@rshono/') ||\n request.startsWith('builtin:') ||\n request.includes('!') ||\n BUNDLED_PACKAGES.test(request) ||\n // Anything reached from the SSR layer, which is where `'use client'` components are rendered on the\n // server. It has to be *compiled* rather than imported by name, because the env-shadow loader is what\n // keeps a secret out of SSR'd HTML and a loader cannot run on a module the bundle only names — an\n // externalized third-party client component is loaded raw at request time and reads the real\n // `process.env`. Widening the loader's rule to cover `node_modules` did not reach this: there was no\n // module for it to run on.\n //\n // Free of the usual bundling trade-off, too. Every module in this layer is in the *browser* bundle as\n // well, so it is already required to be bundleable — a native addon or a `__dirname` file read could\n // not have been a client component in the first place. The RSC layer, where server-only dependencies\n // live, keeps the externals policy.\n contextInfo?.issuerLayer === Layers.ssr\n ) {\n return callback();\n }\n callback(undefined, `module-import ${request}`);\n },\n ],\n resolve: {\n ...serverResolveBase,\n alias: {\n '@rshono/routes$': routesFile,\n '@rshono/server-app$': serverAppAlias,\n // Split on '/' so a preset can declare a POSIX-looking path and still resolve on Windows.\n '@rshono/deploy$': join(FRAMEWORK_DIST, ...preset.runtimeModule.split('/')),\n '@': srcDir,\n },\n },\n module: {\n rules: [\n {\n test: (resource: string) => pageFiles.has(resource),\n enforce: 'pre',\n use: [{ loader: join(FRAMEWORK_DIST, 'builder', 'page-entry-loader.cjs') }],\n },\n {\n // Deliberately not scoped to `srcDir`: a `'use client'` component from `node_modules` is SSR'd in\n // the same layer, and scoping this to the app's own source left those rendering against the real\n // `process.env` while the browser bundle saw the `PUBLIC_`-only view — a hydration mismatch on\n // anything the host sets, and a leak for anything secret. The loader's own layer check is what\n // decides; every other module gets one `includes('process.env')` scan.\n test: /\\.[cm]?[tj]sx?$/,\n enforce: 'pre',\n use: [\n {\n loader: join(FRAMEWORK_DIST, 'builder', 'env-shadow-loader.cjs'),\n // `Object.create` over the real `process`, not a bare `{ env }`: the prelude shadows the whole\n // binding for that module, and `react-dom/server` is in this layer too — anything reading\n // `process.nextTick` or `process.platform` has to still find it. Not a `{ __proto__: … }`\n // literal, whose meaning would change if a minifier ever quoted the key.\n options: {\n prelude: `const process = Object.assign(Object.create(globalThis.process ?? Object.prototype), { env: ${JSON.stringify(publicEnv(isDev))} }); `,\n layer: Layers.ssr,\n },\n },\n ],\n },\n swcRule([...(preset.syntaxTargets ?? NODE_TARGETS)]),\n cssRule(),\n {\n test: /\\.(png|jpe?g|gif|webp|avif|ico|svg|woff2?|ttf|otf)$/i,\n type: 'asset',\n generator: { emit: false },\n },\n { resource: ssrEntry, layer: Layers.ssr },\n {\n resource: rscEntry,\n layer: Layers.rsc,\n resolve: { conditionNames: rscConditionNames },\n },\n {\n issuerLayer: Layers.rsc,\n exclude: ssrEntry,\n resolve: { conditionNames: rscConditionNames },\n },\n ],\n },\n plugins: [\n pageScanPlugin,\n new ServerPlugin({ onServerComponentChanges }),\n // Bakes rshono.config.ts into the bundle, read back as `__RSHONO_CONFIG__` at request time.\n new rspack.DefinePlugin({ __RSHONO_CONFIG__: JSON.stringify(resolveServerConfig(config, { isDev, outDir })) }),\n ],\n performance: false,\n };\n\n // The platform's overrides first, then the user's hook — so an app can adjust whatever a preset decided.\n preset.configureServer?.(serverConfig);\n\n const rspackHook = config.rspack;\n if (rspackHook) {\n return [\n rspackHook(clientConfig, { isServer: false, isDev }) ?? clientConfig,\n rspackHook(serverConfig, { isServer: true, isDev }) ?? serverConfig,\n ];\n }\n return [clientConfig, serverConfig];\n}\n"]}
|
package/dist/cli/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,iGAAiG;IACjG,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,iGAAiG;IACjG,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEvE"}
|
package/dist/cli/build.js
CHANGED
|
@@ -48,9 +48,9 @@ export async function buildCommand(options) {
|
|
|
48
48
|
console.log(` • prerendered ${written.length} static page(s): ${written.join(', ')}`);
|
|
49
49
|
if (skipped.length > 0)
|
|
50
50
|
console.log(` • skipped ${skipped.length} (will SSR per request)`);
|
|
51
|
-
//
|
|
51
|
+
// Before `finalize`, so a preset that copies `dist/` into a platform layout takes it along.
|
|
52
52
|
writeBuildMarker(distDir, preset.name);
|
|
53
|
-
// Last, so a preset arranging its output finds every piece of the build
|
|
53
|
+
// Last, so a preset arranging its output finds every piece of the build on disk.
|
|
54
54
|
await preset.finalize?.({
|
|
55
55
|
rootDir,
|
|
56
56
|
distDir,
|
|
@@ -59,6 +59,10 @@ export async function buildCommand(options) {
|
|
|
59
59
|
ssgDir,
|
|
60
60
|
});
|
|
61
61
|
console.log(` ✓ build complete — ${preset.deployHint}`);
|
|
62
|
+
// Rspack's worker pool can keep the loop alive after `close()`, so the exit is explicit — but a piped
|
|
63
|
+
// stdout is asynchronous, and exiting drops whatever has not drained. In CI that is exactly the lines
|
|
64
|
+
// saying what was built and where it went. A zero-length write's callback fires behind the real ones.
|
|
65
|
+
await new Promise((resolve) => process.stdout.write('', () => resolve()));
|
|
62
66
|
process.exit(0);
|
|
63
67
|
}
|
|
64
68
|
//# sourceMappingURL=build.js.map
|
package/dist/cli/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmB,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AASzD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACtD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjC,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9D,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC3B,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE;gBAClB,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,MAAO,CAAC,CAAC;YACxB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEjE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1C,IAAI,aAAa,GAAkB,IAAI,CAAC;IACxC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC;IACnC,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAGpF,CAAC;IACF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,qBAAqB,CAAC;QACvD,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAC7C,MAAM;QACN,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,MAAM,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/G,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,MAAM,yBAAyB,CAAC,CAAC;IAE5F,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { rspack, type MultiStats } from '@rspack/core';\nimport type { Hono } from 'hono';\nimport { cpSync, existsSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { BUILD_OUT_DIR, createConfigs } from '../builder/rspack-config.js';\nimport type { RshonoConfig } from '../config.js';\nimport { writeBuildMarker } from '../deploy/build-marker.js';\nimport type { DeployPreset } from '../deploy/presets.js';\nimport type { Route } from '../router.js';\nimport { prerenderStaticRoutes } from '../server/ssg.js';\n\ninterface BuildOptions {\n rootDir: string;\n config: RshonoConfig;\n /** The platform to build for, already resolved from the flag, the environment and the config. */\n preset: DeployPreset;\n}\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const { rootDir, config, preset } = options;\n const distDir = join(rootDir, BUILD_OUT_DIR);\n\n console.log(' • building client + server bundles…');\n const configs = createConfigs({ rootDir, isDev: false, config, preset });\n const compiler = rspack(configs);\n\n const stats = await new Promise<MultiStats>((resolve, reject) => {\n compiler.run((err, result) => {\n compiler.close(() => {\n if (err) reject(err);\n else resolve(result!);\n });\n });\n });\n\n if (stats.hasErrors()) {\n console.error(stats.toString({ preset: 'errors-warnings', colors: true }));\n process.exit(1);\n }\n console.log(stats.toString({ preset: 'summary', colors: true }));\n\n const publicDir = join(rootDir, 'public');\n let distPublicDir: string | null = null;\n if (existsSync(publicDir)) {\n distPublicDir = join(distDir, 'public');\n cpSync(publicDir, distPublicDir, { recursive: true });\n console.log(' • copied public/ into dist/public (served at /)');\n }\n\n const ssgDir = join(distDir, 'ssg');\n await rm(ssgDir, { recursive: true, force: true });\n process.env.RSHONO_PRERENDER = '1';\n const bundle = (await import(pathToFileURL(join(distDir, 'server', 'main.mjs')).href)) as {\n app: Hono;\n routes: readonly Route[];\n };\n const { written, skipped } = await prerenderStaticRoutes({\n routes: bundle.routes,\n fetch: (request) => bundle.app.fetch(request),\n ssgDir,\n siteUrl: config.siteUrl,\n });\n if (written.length > 0) console.log(` • prerendered ${written.length} static page(s): ${written.join(', ')}`);\n if (skipped.length > 0) console.log(` • skipped ${skipped.length} (will SSR per request)`);\n\n // Before `finalize`, so a preset that copies `dist/` into a platform layout takes it along.\n writeBuildMarker(distDir, preset.name);\n\n // Last, so a preset arranging its output finds every piece of the build on disk.\n await preset.finalize?.({\n rootDir,\n distDir,\n staticDir: join(distDir, 'static'),\n publicDir: distPublicDir,\n ssgDir,\n });\n\n console.log(` ✓ build complete — ${preset.deployHint}`);\n\n // Rspack's worker pool can keep the loop alive after `close()`, so the exit is explicit — but a piped\n // stdout is asynchronous, and exiting drops whatever has not drained. In CI that is exactly the lines\n // saying what was built and where it went. A zero-length write's callback fires behind the real ones.\n await new Promise<void>((resolve) => process.stdout.write('', () => resolve()));\n process.exit(0);\n}\n"]}
|
package/dist/cli/dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA0BjD,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAiPnE"}
|
package/dist/cli/dev.js
CHANGED
|
@@ -16,12 +16,9 @@ function describe(error) {
|
|
|
16
16
|
return error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Whether nothing is listening on the port yet — checked before the output directory is emptied
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* wipes the directory that server is still importing route chunks from, and only then exits on
|
|
23
|
-
* EADDRINUSE. The first server keeps serving from files that no longer exist, and its watcher never
|
|
24
|
-
* re-emits them — it believes it already wrote them — so it 500s until it is restarted.
|
|
19
|
+
* Whether nothing is listening on the port yet — checked before the output directory is emptied, because a
|
|
20
|
+
* second `rshono dev` would otherwise wipe the chunks the running one is still importing and only then exit
|
|
21
|
+
* on EADDRINUSE.
|
|
25
22
|
*/
|
|
26
23
|
function portAvailable(port, hostname) {
|
|
27
24
|
const { promise, resolve } = Promise.withResolvers();
|
|
@@ -33,10 +30,10 @@ function portAvailable(port, hostname) {
|
|
|
33
30
|
export async function devCommand(options) {
|
|
34
31
|
const { rootDir, config } = options;
|
|
35
32
|
const port = options.port ?? SERVER_DEFAULTS.port;
|
|
36
|
-
// Its own directory, never `dist/`: a `rshono build` in another terminal must not be able to
|
|
37
|
-
//
|
|
33
|
+
// Its own directory, never `dist/`: a `rshono build` in another terminal must not be able to delete the
|
|
34
|
+
// chunks this server is still importing.
|
|
38
35
|
const outDir = join(rootDir, DEV_OUT_DIR);
|
|
39
|
-
// Before the `rm` below, not at `serve` where the bind
|
|
36
|
+
// Before the `rm` below, not at `serve` where the bind happens — see {@link portAvailable}.
|
|
40
37
|
if (!(await portAvailable(port, '127.0.0.1'))) {
|
|
41
38
|
console.error(` ✗ port ${port} is already in use`);
|
|
42
39
|
process.exit(1);
|
|
@@ -48,9 +45,8 @@ export async function devCommand(options) {
|
|
|
48
45
|
let clientHash;
|
|
49
46
|
const sseChunk = (data) => encoder.encode(`data: ${JSON.stringify(data)}\n\n`);
|
|
50
47
|
/**
|
|
51
|
-
* Writes one already-encoded SSE frame to every open client
|
|
52
|
-
*
|
|
53
|
-
* always reached first — so a failed write is what retires a client.
|
|
48
|
+
* Writes one already-encoded SSE frame to every open client. A failed write is what retires a client:
|
|
49
|
+
* `cancel` is not always reached first when a browser navigates away.
|
|
54
50
|
*/
|
|
55
51
|
function sendToAll(chunk) {
|
|
56
52
|
for (const controller of sseClients) {
|
|
@@ -70,8 +66,8 @@ export async function devCommand(options) {
|
|
|
70
66
|
rootDir,
|
|
71
67
|
isDev: true,
|
|
72
68
|
config,
|
|
73
|
-
// Always Node, whatever `deploy` says:
|
|
74
|
-
//
|
|
69
|
+
// Always Node, whatever `deploy` says: that is a property of `build` output, and the dev server runs the
|
|
70
|
+
// bundle in a worker thread of this process.
|
|
75
71
|
preset: NODE_PRESET,
|
|
76
72
|
onServerComponentChanges: () => {
|
|
77
73
|
serverComponentsChanged = true;
|
|
@@ -95,7 +91,9 @@ export async function devCommand(options) {
|
|
|
95
91
|
env: process.env,
|
|
96
92
|
});
|
|
97
93
|
const timeout = setTimeout(() => {
|
|
98
|
-
worker
|
|
94
|
+
// Nothing waits on the termination: the promise below is already being rejected, and a worker that
|
|
95
|
+
// never reported ready has no state left worth draining.
|
|
96
|
+
void worker.terminate();
|
|
99
97
|
reject(new Error(`server worker did not become ready within ${WORKER_READY_TIMEOUT_MS / 1000}s`));
|
|
100
98
|
}, WORKER_READY_TIMEOUT_MS);
|
|
101
99
|
let ready = false;
|
|
@@ -106,9 +104,8 @@ export async function devCommand(options) {
|
|
|
106
104
|
resolve({ worker, port: message.port });
|
|
107
105
|
}
|
|
108
106
|
});
|
|
109
|
-
// `on`, not `once`: an error
|
|
110
|
-
//
|
|
111
|
-
// an uncaught exception that takes the dev server down with the worker.
|
|
107
|
+
// `on`, not `once`: an error after the worker is ready has no pending promise left to reject, and a
|
|
108
|
+
// consumed `once` would leave it unlistened — which Node turns into an uncaught exception here.
|
|
112
109
|
worker.on('error', (error) => {
|
|
113
110
|
if (ready) {
|
|
114
111
|
console.error(' ✗ server worker crashed:', error);
|
|
@@ -121,10 +118,8 @@ export async function devCommand(options) {
|
|
|
121
118
|
if (worker === currentWorker && code !== 0) {
|
|
122
119
|
console.error(` ✗ server worker exited with code ${code} — waiting for the next rebuild`);
|
|
123
120
|
currentWorker = null;
|
|
124
|
-
// Opened with the reason rather than left closed
|
|
125
|
-
//
|
|
126
|
-
// saying why. `hooks.invalid` installs a fresh closed gate the moment a file changes, so the
|
|
127
|
-
// next build still holds requests until the worker is back.
|
|
121
|
+
// Opened with the reason rather than left closed, so a request arriving before the next rebuild sees
|
|
122
|
+
// it instead of hanging. `hooks.invalid` installs a fresh closed gate as soon as a file changes.
|
|
128
123
|
workerGate = createGate();
|
|
129
124
|
workerGate.open({ error: `The server worker exited with code ${code}. See the terminal for the error it crashed with.` });
|
|
130
125
|
}
|
|
@@ -162,9 +157,8 @@ export async function devCommand(options) {
|
|
|
162
157
|
gate.open({ error: describe(error) });
|
|
163
158
|
}
|
|
164
159
|
});
|
|
165
|
-
// No link in this queue may be left rejected: `.then` on a rejected promise short-circuits, and
|
|
166
|
-
//
|
|
167
|
-
// answers nothing and explains nothing. The `try` above covers the restart; this covers the rest.
|
|
160
|
+
// No link in this queue may be left rejected: `.then` on a rejected promise short-circuits, and from there
|
|
161
|
+
// no worker is spawned and no gate is opened again.
|
|
168
162
|
restartChain = restartChain.catch((error) => {
|
|
169
163
|
console.error(' ✗ dev server restart failed:', error);
|
|
170
164
|
gate.open({ error: describe(error) });
|
|
@@ -194,7 +188,7 @@ export async function devCommand(options) {
|
|
|
194
188
|
});
|
|
195
189
|
const front = new Hono();
|
|
196
190
|
front.route('/_static', createStaticAssetsApp({ root: join(outDir, 'static'), isDev: true }));
|
|
197
|
-
front.get('/_rshono/hmr', (
|
|
191
|
+
front.get('/_rshono/hmr', () => {
|
|
198
192
|
let ctrl;
|
|
199
193
|
const stream = new ReadableStream({
|
|
200
194
|
start(controller) {
|
|
@@ -215,8 +209,8 @@ export async function devCommand(options) {
|
|
|
215
209
|
},
|
|
216
210
|
});
|
|
217
211
|
});
|
|
218
|
-
// An SSE comment, not a message: it keeps an idle connection off a proxy's timeout without the
|
|
219
|
-
//
|
|
212
|
+
// An SSE comment, not a message: it keeps an idle connection off a proxy's timeout without the client
|
|
213
|
+
// having to know a frame type that means nothing.
|
|
220
214
|
const ping = encoder.encode(': ping\n\n');
|
|
221
215
|
setInterval(() => sendToAll(ping), 15_000).unref();
|
|
222
216
|
front.all('*', async (c) => {
|
|
@@ -226,27 +220,23 @@ export async function devCommand(options) {
|
|
|
226
220
|
}
|
|
227
221
|
const incoming = new URL(c.req.url);
|
|
228
222
|
const target = `http://127.0.0.1:${workerPort}${incoming.pathname}${incoming.search}`;
|
|
229
|
-
// Hono's proxy helper rather than a hand-rolled `fetch`: it carries the method, the streamed body
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
// replaces the set wholesale, so the request's own are spread back in first.
|
|
223
|
+
// Hono's proxy helper rather than a hand-rolled `fetch`: it carries the method, the streamed body (with
|
|
224
|
+
// the `duplex` Node requires) and the client's abort signal, and strips the hop-by-hop headers on the way
|
|
225
|
+
// back. `headers` replaces the set wholesale, so the request's own are spread back in first.
|
|
233
226
|
const response = await proxy(target, {
|
|
234
227
|
raw: c.req.raw,
|
|
235
|
-
// The worker's redirects are the app's answer to this request,
|
|
236
|
-
// they have to reach the browser, with the internal address rewritten off them below.
|
|
228
|
+
// The worker's redirects are the app's answer to this request, to be rewritten below and passed on.
|
|
237
229
|
redirect: 'manual',
|
|
238
230
|
headers: {
|
|
239
231
|
...c.req.header(),
|
|
240
|
-
// This front-end *is* the proxy the app sits behind,
|
|
241
|
-
//
|
|
242
|
-
// 127.0.0.1 port instead of the address the browser actually used.
|
|
232
|
+
// This front-end *is* the proxy the app sits behind, which is why `trustProxy` is forced on in dev:
|
|
233
|
+
// without these the app resolves every URL against the worker's random 127.0.0.1 port.
|
|
243
234
|
'x-forwarded-host': incoming.host,
|
|
244
235
|
'x-forwarded-proto': incoming.protocol.replace(':', ''),
|
|
245
236
|
},
|
|
246
237
|
});
|
|
247
|
-
// A redirect to the worker's own address has to become a relative one, or the browser leaves the
|
|
248
|
-
//
|
|
249
|
-
// headers are still mutable, so the rewrite happens in place.
|
|
238
|
+
// A redirect to the worker's own address has to become a relative one, or the browser leaves the dev
|
|
239
|
+
// server for a random port only this process knows about.
|
|
250
240
|
const location = response.headers.get('location');
|
|
251
241
|
const loc = location ? URL.parse(location, target) : null;
|
|
252
242
|
if (loc && loc.host === `127.0.0.1:${workerPort}`) {
|