@alxia/react-router 0.3.0 → 0.4.0
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/README.md +20 -12
- package/dist/vite/bundle.d.ts +33 -0
- package/dist/vite/bundle.d.ts.map +1 -0
- package/dist/vite/index.d.ts +4 -0
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +16 -2
- package/dist/vite/index.js.map +5 -4
- package/docs/guide.md +98 -19
- package/docs/roadmap.md +7 -1
- package/docs/troubleshooting.md +52 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -288,7 +288,9 @@ build, it adds:
|
|
|
288
288
|
bundled, and loaded in dev, as that variant;
|
|
289
289
|
- `bun` and `bun:*` to `resolve.builtins`: Bun's own modules stay imports
|
|
290
290
|
of `build/server/index.js`;
|
|
291
|
-
- `build.target: 'esnext'`, where Vite's default targets browsers
|
|
291
|
+
- `build.target: 'esnext'`, where Vite's default targets browsers;
|
|
292
|
+
- in the build only, `resolve.noExternal: true`: every package is bundled
|
|
293
|
+
into `build/server/index.js`, so `build/` runs with no `node_modules`.
|
|
292
294
|
|
|
293
295
|
```ts
|
|
294
296
|
// app/server.ts: Bun's modules, bundled as they are
|
|
@@ -308,7 +310,19 @@ export default createServer({
|
|
|
308
310
|
What the app sets wins: its own conditions and builtins are kept, `bun` is
|
|
309
311
|
added beside them, and a `build.target` it set is left as it is.
|
|
310
312
|
`ssr.target` stays `node`, and no polyfill is added; an app that sets
|
|
311
|
-
`ssr.target: 'webworker'` itself gets none of this, only Vite's defaults.
|
|
313
|
+
`ssr.target: 'webworker'` itself gets none of this, only Vite's defaults.
|
|
314
|
+
A package that cannot be bundled, a native addon, stays external when the
|
|
315
|
+
app names it, and every package does with `ssr.external: true`:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
// vite.config.ts: sharp imported from node_modules at runtime
|
|
319
|
+
export default defineConfig({
|
|
320
|
+
ssr: { external: ['sharp'] },
|
|
321
|
+
plugins: [reactRouter(), alxia()],
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
The
|
|
312
326
|
[guide](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/guide.md#built-for-bun)
|
|
313
327
|
has each option and why.
|
|
314
328
|
|
|
@@ -316,14 +330,10 @@ has each option and why.
|
|
|
316
330
|
|
|
317
331
|
A multi-stage `Dockerfile` on Bun's official image, as `@alxia/create`'s
|
|
318
332
|
`react-router` template ships it. For an app from `create-react-router`,
|
|
319
|
-
it replaces the template's, which runs on Node
|
|
333
|
+
it replaces the template's, which runs on Node. The build is
|
|
334
|
+
self-contained, so the image holds `build/` alone, no `node_modules`:
|
|
320
335
|
|
|
321
336
|
```dockerfile
|
|
322
|
-
FROM oven/bun:1 AS production-dependencies
|
|
323
|
-
WORKDIR /app
|
|
324
|
-
COPY package.json bun.lock* bunfig.toml* ./
|
|
325
|
-
RUN bun install --frozen-lockfile --production
|
|
326
|
-
|
|
327
337
|
FROM oven/bun:1 AS build
|
|
328
338
|
WORKDIR /app
|
|
329
339
|
COPY package.json bun.lock* bunfig.toml* ./
|
|
@@ -334,12 +344,10 @@ RUN bun run build
|
|
|
334
344
|
FROM oven/bun:1
|
|
335
345
|
WORKDIR /app
|
|
336
346
|
ENV NODE_ENV=production
|
|
337
|
-
COPY package.json ./
|
|
338
|
-
COPY --from=production-dependencies /app/node_modules ./node_modules
|
|
339
347
|
COPY --from=build /app/build ./build
|
|
340
348
|
USER bun
|
|
341
349
|
EXPOSE 3000
|
|
342
|
-
CMD ["bun", "build/server/index.js"]
|
|
350
|
+
CMD ["bun", "--no-install", "build/server/index.js"]
|
|
343
351
|
```
|
|
344
352
|
|
|
345
353
|
```sh
|
|
@@ -350,7 +358,7 @@ docker run -p 3000:3000 my-app
|
|
|
350
358
|
Keep the template's `.dockerignore`, and commit `bun.lock`. The server
|
|
351
359
|
runs as the non-root `bun` user, on `PORT` (3000). The
|
|
352
360
|
[guide](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/guide.md#docker)
|
|
353
|
-
has the commented file.
|
|
361
|
+
has the commented file, and what to copy for a package left external.
|
|
354
362
|
|
|
355
363
|
## Traps
|
|
356
364
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server build, self-contained: every dependency bundled into
|
|
3
|
+
* `build/server/index.js`, so that running it needs `build/` and Bun, and
|
|
4
|
+
* no `node_modules`. A Docker image's final stage copies `build/` alone.
|
|
5
|
+
*/
|
|
6
|
+
import type { EnvironmentOptions } from 'vite';
|
|
7
|
+
/**
|
|
8
|
+
* What the plugin adds to the `ssr` environment under `react-router build`,
|
|
9
|
+
* given its options as the config and the plugins left them:
|
|
10
|
+
* `resolve.noExternal: true`, every package bundled. Never in dev, where
|
|
11
|
+
* Vite's SSR runner loads the packages from `node_modules`.
|
|
12
|
+
*
|
|
13
|
+
* What the app set wins:
|
|
14
|
+
*
|
|
15
|
+
* - `ssr.external: ['sharp']`, or the same on `environments.ssr.resolve`,
|
|
16
|
+
* keeps those packages external, imported from `node_modules` at
|
|
17
|
+
* runtime: Vite reads `external` before `noExternal`. Bun's own modules,
|
|
18
|
+
* `bun` and `bun:*`, and Node's are builtins, external whatever this says.
|
|
19
|
+
* - `ssr.external: true` keeps every package external, Vite's own default:
|
|
20
|
+
* the plugin adds nothing then.
|
|
21
|
+
* - `ssr.noExternal`, a list, is a subset of everything: it changes nothing.
|
|
22
|
+
*
|
|
23
|
+
* React Router's own plugin reads `noExternal: true` and adds no externals
|
|
24
|
+
* of its own; it runs after this one, which is `enforce: 'pre'`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function bundledEnvironment(options: EnvironmentOptions): EnvironmentOptions | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Everything the plugin adds to the `ssr` environment: built for Bun under
|
|
29
|
+
* either command, and self-contained under `build` alone. In dev, Vite's
|
|
30
|
+
* SSR runner loads the packages from `node_modules`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ssrEnvironment(options: EnvironmentOptions, command: 'build' | 'serve'): EnvironmentOptions;
|
|
33
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/vite/bundle.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAG/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,kBAAkB,GACzB,kBAAkB,GAAG,SAAS,CAGhC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,OAAO,GAAG,OAAO,GACxB,kBAAkB,CAKpB"}
|
package/dist/vite/index.d.ts
CHANGED
|
@@ -28,6 +28,10 @@ export interface AlxiaOptions {
|
|
|
28
28
|
* - **Built for Bun**: the `ssr` environment resolves packages with the
|
|
29
29
|
* `bun` export condition, leaves `bun` and `bun:*` external, and targets
|
|
30
30
|
* `esnext` unless the app set a target. What the app set is kept.
|
|
31
|
+
* - **Self-contained**: `react-router build` bundles every package into
|
|
32
|
+
* `build/server/index.js` (`ssr.noExternal: true`), so `build/` runs with
|
|
33
|
+
* no `node_modules`. `ssr.external` keeps the packages it names external,
|
|
34
|
+
* and `ssr.external: true` all of them.
|
|
31
35
|
*
|
|
32
36
|
* The server is `app/server.ts`'s default export, `createServer()` from
|
|
33
37
|
* `@alxia/react-router`, or without that file `createServer()` as it is.
|
package/dist/vite/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAgBnD,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAgBnD,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CA+ExD"}
|
package/dist/vite/index.js
CHANGED
|
@@ -41,6 +41,20 @@ function bunEnvironment(options) {
|
|
|
41
41
|
return added;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// src/vite/bundle.ts
|
|
45
|
+
function bundledEnvironment(options) {
|
|
46
|
+
if (options.resolve?.external === true)
|
|
47
|
+
return;
|
|
48
|
+
return { resolve: { noExternal: true } };
|
|
49
|
+
}
|
|
50
|
+
function ssrEnvironment(options, command) {
|
|
51
|
+
const added = bunEnvironment(options);
|
|
52
|
+
const bundled = command === "build" ? bundledEnvironment(options) : undefined;
|
|
53
|
+
if (bundled === undefined)
|
|
54
|
+
return added;
|
|
55
|
+
return { ...added, resolve: { ...added.resolve, ...bundled.resolve } };
|
|
56
|
+
}
|
|
57
|
+
|
|
44
58
|
// src/vite/config.ts
|
|
45
59
|
import { existsSync } from "node:fs";
|
|
46
60
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
@@ -371,7 +385,7 @@ function alxia(options = {}) {
|
|
|
371
385
|
configEnvironment(name, options, env) {
|
|
372
386
|
if (name !== "ssr" || env.isSsrTargetWebworker === true)
|
|
373
387
|
return;
|
|
374
|
-
return
|
|
388
|
+
return ssrEnvironment(options, env.command);
|
|
375
389
|
},
|
|
376
390
|
configResolved(resolved) {
|
|
377
391
|
config = resolved;
|
|
@@ -426,5 +440,5 @@ export {
|
|
|
426
440
|
alxia
|
|
427
441
|
};
|
|
428
442
|
|
|
429
|
-
//# debugId=
|
|
443
|
+
//# debugId=68EB80E9F1CC79CC64756E2164756E21
|
|
430
444
|
//# sourceMappingURL=index.js.map
|
package/dist/vite/index.js.map
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/vite/index.ts", "../src/vite/bun.ts", "../src/vite/config.ts", "../src/vite/node.ts", "../src/vite/socket.ts", "../src/vite/dev.ts", "../src/vite/preview.ts", "../src/vite/runtime.ts"],
|
|
3
|
+
"sources": ["../src/vite/index.ts", "../src/vite/bun.ts", "../src/vite/bundle.ts", "../src/vite/config.ts", "../src/vite/node.ts", "../src/vite/socket.ts", "../src/vite/dev.ts", "../src/vite/preview.ts", "../src/vite/runtime.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * `@alxia/react-router/vite`: `alxia()`, the Vite plugin that makes alxia\n * the server of a React Router app, under `react-router dev` and in\n * `react-router build`, with or without an `app/server.ts`.\n */\nimport { relative } from 'node:path';\n// Types only: the plugin runs on whichever Vite the app has, never on a\n// copy of this package's own.\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport {
|
|
5
|
+
"/**\n * `@alxia/react-router/vite`: `alxia()`, the Vite plugin that makes alxia\n * the server of a React Router app, under `react-router dev` and in\n * `react-router build`, with or without an `app/server.ts`.\n */\nimport { relative } from 'node:path';\n// Types only: the plugin runs on whichever Vite the app has, never on a\n// copy of this package's own.\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport { ssrEnvironment } from './bundle';\nimport {\n\tclientPath,\n\tcontextOf,\n\tDEFAULT,\n\tisChildCompiler,\n\tSERVER,\n\tserverBuildOptions,\n\tserverFile,\n} from './config';\nimport { serveDev } from './dev';\nimport { NAME, PASS_THROUGH, serverEntry } from './entry';\nimport { servePreview } from './preview';\nimport { requireBun } from './runtime';\n\nexport interface AlxiaOptions {\n\t/**\n\t * The server file, relative to Vite's root: a module whose default export\n\t * is `createServer()` from `@alxia/react-router`. By default `server.ts`\n\t * in React Router's app directory, `app/server.ts`, when it exists, and\n\t * otherwise `createServer()` with no options.\n\t */\n\treadonly entry?: string;\n}\n\nconst RESOLVED_SERVER = `\\0${SERVER}`;\nconst RESOLVED_DEFAULT = `\\0${DEFAULT}`;\n\n/**\n * The Vite plugin that makes alxia the server of a React Router app,\n * anywhere in `plugins`:\n *\n * ```ts\n * export default defineConfig({ plugins: [alxia(), reactRouter()] });\n * ```\n *\n * - **`react-router dev`**: every request Vite does not answer itself —\n * pages, data, `/api` — goes to the server, loaded through Vite's SSR\n * runner. HMR, an edit to the server, the app's own context keys and\n * its WebSocket routes work, with no restart.\n * - **`react-router build`**: `build/server/index.js` is the server, with\n * React Router's build inside it. `bun build/server/index.js` listens on\n * `PORT` (3000) and `HOST` (`0.0.0.0`); importing it starts nothing.\n * - **`vite preview`**: every request goes to that built server, as it\n * would answer it; so does React Router's prerendering.\n * - **Built for Bun**: the `ssr` environment resolves packages with the\n * `bun` export condition, leaves `bun` and `bun:*` external, and targets\n * `esnext` unless the app set a target. What the app set is kept.\n * - **Self-contained**: `react-router build` bundles every package into\n * `build/server/index.js` (`ssr.noExternal: true`), so `build/` runs with\n * no `node_modules`. `ssr.external` keeps the packages it names external,\n * and `ssr.external: true` all of them.\n *\n * The server is `app/server.ts`'s default export, `createServer()` from\n * `@alxia/react-router`, or without that file `createServer()` as it is.\n */\nexport function alxia(options: AlxiaOptions = {}): Plugin {\n\tlet config: ResolvedConfig | undefined;\n\tlet enabled = true;\n\n\treturn {\n\t\tname: NAME,\n\t\t// Before React Router's plugin, wherever it is listed: its config reads\n\t\t// the server build's input from this one's, and its dev middleware,\n\t\t// which would render the pages without alxia, comes after this one's.\n\t\tenforce: 'pre',\n\t\tconfig(_config, env) {\n\t\t\tif (env.command !== 'build') return;\n\t\t\t// Vite 7's types know neither `rolldownVersion` nor `rolldownOptions`.\n\t\t\tconst meta = this.meta as { readonly rolldownVersion?: string };\n\t\t\tconst bundler = serverBuildOptions(meta.rolldownVersion !== undefined);\n\t\t\treturn { environments: { ssr: { build: bundler as never } } };\n\t\t},\n\t\tconfigEnvironment(name, options, env) {\n\t\t\t// After every config hook, React Router's included: the server\n\t\t\t// environment as the app and the plugins left it, built for Bun.\n\t\t\t// An app that chose `ssr.target: 'webworker'` keeps Vite's own.\n\t\t\tif (name !== 'ssr' || env.isSsrTargetWebworker === true) return;\n\t\t\treturn ssrEnvironment(options, env.command);\n\t\t},\n\t\tconfigResolved(resolved) {\n\t\t\tconfig = resolved;\n\t\t\t// React Router compiles route modules in a Vite server of its own,\n\t\t\t// with every plugin but its own: there is nothing to serve there.\n\t\t\tif (isChildCompiler(resolved)) {\n\t\t\t\tenabled = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst rr = contextOf(resolved);\n\t\t\t// A single-page app has no server to be.\n\t\t\tenabled = rr.ssr;\n\t\t\tif (enabled && rr.serverBundles !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${NAME}: serverBundles splits React Router's server build in several, and alxia serves one. Remove serverBundles from react-router.config.ts.`,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\tresolveId(id) {\n\t\t\tif (id === SERVER) return RESOLVED_SERVER;\n\t\t\tif (id === DEFAULT) return RESOLVED_DEFAULT;\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_SERVER && id !== RESOLVED_DEFAULT) return;\n\t\t\tif (config === undefined) return;\n\t\t\t// Disabled, a single-page app: React Router still builds its server\n\t\t\t// build, to render index.html, from this input.\n\t\t\tif (!enabled) return PASS_THROUGH;\n\t\t\tconst dev = config.command === 'serve';\n\t\t\tconst file =\n\t\t\t\tid === RESOLVED_DEFAULT ? undefined : serverFile(options.entry, config);\n\t\t\treturn serverEntry({\n\t\t\t\tfile,\n\t\t\t\tlabel: file === undefined ? '' : relative(config.root, file),\n\t\t\t\tdev,\n\t\t\t\tclient: dev ? undefined : clientPath(config),\n\t\t\t});\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\trequireBun('react-router dev');\n\t\t\treturn serveDev(server, options.entry);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\t// React Router prerenders through a preview server of its own,\n\t\t\t// resolved as `serve` too: the message cannot tell the two apart.\n\t\t\trequireBun(\n\t\t\t\t'vite preview, or a react-router build that prerenders,',\n\t\t\t\t'bun --bun vite preview or bun --bun react-router build',\n\t\t\t);\n\t\t\t// Before Vite's own files: the built server answers every request.\n\t\t\tservePreview(server);\n\t\t},\n\t};\n}\n",
|
|
6
6
|
"/**\n * The server build, for Bun: what the plugin adds to Vite's `ssr`\n * environment so that `build/server/index.js` is built for the runtime\n * that runs it, and so is the module the dev server loads.\n */\nimport { builtinModules } from 'node:module';\nimport type { EnvironmentOptions } from 'vite';\n\n/** The export condition Bun resolves a package by, and the plugin adds. */\nconst BUN_CONDITION = 'bun';\n\n/**\n * Vite's own builtins for a server environment (its `nodeLikeBuiltins`),\n * which it uses when the config names none: Node's modules, `node:*` and\n * `bun:*`. Bare `bun` is among Node's modules only when Vite runs on Bun.\n */\nconst VITE_BUILTINS: readonly (string | RegExp)[] = [\n\t...builtinModules.filter((id) => !id.includes(':')),\n\t/^node:/,\n\t/^bun:/,\n];\n\n/**\n * Vite's default conditions for a server environment, and for its\n * externals, which it uses when the config names none. React Router's\n * plugin always names them; these are for a config where nothing did.\n */\nconst VITE_CONDITIONS = ['module', 'node', 'development|production'];\nconst VITE_EXTERNAL_CONDITIONS = ['node', 'module-sync'];\n\n/** Bun's own modules, which no bundler should try to resolve: `bun` and `bun:*`. */\nconst BUN_BUILTINS: readonly (string | RegExp)[] = [BUN_CONDITION, /^bun:/];\n\n/**\n * What to merge into `present` so that it holds `wanted`: Vite replaces its\n * default with any value set, so an unset option gets the default too.\n * Strings compare by value, patterns by source.\n */\nfunction adding<T extends string | RegExp>(\n\tpresent: readonly T[] | undefined,\n\tfallback: readonly T[],\n\twanted: readonly T[],\n): T[] {\n\tconst list = present ?? fallback;\n\tconst has = (item: T) =>\n\t\tlist.some((other) =>\n\t\t\ttypeof item === 'string'\n\t\t\t\t? other === item\n\t\t\t\t: other instanceof RegExp && other.source === item.source,\n\t\t);\n\treturn [\n\t\t...(present === undefined ? fallback : []),\n\t\t...wanted.filter((item) => !has(item)),\n\t];\n}\n\n/**\n * What the plugin adds to the `ssr` environment, given its options as the\n * config and every plugin's `config` hook left them. Vite merges the\n * result into them, concatenating arrays, so what the app set is kept:\n *\n * - `resolve.conditions` and `resolve.externalConditions` gain `bun`, so a\n * package that exports a `bun` variant is bundled, and checked, as Bun\n * would load it. Which variant wins stays the package's own order.\n * - `resolve.builtins` gains `bun` and `bun:*`: left external, whichever\n * runtime runs Vite. Vite's own builtins are kept when the app names none.\n * - `build.target` is `esnext`, Bun's, unless the app set one, at the top\n * level or on the environment.\n *\n * `ssr.target` stays `node`: Bun runs Node's modules, and `webworker`\n * would bundle every dependency with the browser's conditions. An app that\n * sets `webworker` itself gets none of this: the plugin leaves that\n * environment to Vite's own defaults.\n */\nexport function bunEnvironment(\n\toptions: EnvironmentOptions,\n): EnvironmentOptions {\n\tconst resolve = options.resolve ?? {};\n\tconst added: EnvironmentOptions = {\n\t\tresolve: {\n\t\t\tconditions: adding(resolve.conditions, VITE_CONDITIONS, [BUN_CONDITION]),\n\t\t\texternalConditions: adding(\n\t\t\t\tresolve.externalConditions,\n\t\t\t\tVITE_EXTERNAL_CONDITIONS,\n\t\t\t\t[BUN_CONDITION],\n\t\t\t),\n\t\t\tbuiltins: adding(resolve.builtins, VITE_BUILTINS, BUN_BUILTINS),\n\t\t},\n\t};\n\tif (options.build?.target === undefined) {\n\t\tadded.build = { target: 'esnext' };\n\t}\n\treturn added;\n}\n",
|
|
7
|
+
"/**\n * The server build, self-contained: every dependency bundled into\n * `build/server/index.js`, so that running it needs `build/` and Bun, and\n * no `node_modules`. A Docker image's final stage copies `build/` alone.\n */\nimport type { EnvironmentOptions } from 'vite';\nimport { bunEnvironment } from './bun';\n\n/**\n * What the plugin adds to the `ssr` environment under `react-router build`,\n * given its options as the config and the plugins left them:\n * `resolve.noExternal: true`, every package bundled. Never in dev, where\n * Vite's SSR runner loads the packages from `node_modules`.\n *\n * What the app set wins:\n *\n * - `ssr.external: ['sharp']`, or the same on `environments.ssr.resolve`,\n * keeps those packages external, imported from `node_modules` at\n * runtime: Vite reads `external` before `noExternal`. Bun's own modules,\n * `bun` and `bun:*`, and Node's are builtins, external whatever this says.\n * - `ssr.external: true` keeps every package external, Vite's own default:\n * the plugin adds nothing then.\n * - `ssr.noExternal`, a list, is a subset of everything: it changes nothing.\n *\n * React Router's own plugin reads `noExternal: true` and adds no externals\n * of its own; it runs after this one, which is `enforce: 'pre'`.\n */\nexport function bundledEnvironment(\n\toptions: EnvironmentOptions,\n): EnvironmentOptions | undefined {\n\tif (options.resolve?.external === true) return undefined;\n\treturn { resolve: { noExternal: true } };\n}\n\n/**\n * Everything the plugin adds to the `ssr` environment: built for Bun under\n * either command, and self-contained under `build` alone. In dev, Vite's\n * SSR runner loads the packages from `node_modules`.\n */\nexport function ssrEnvironment(\n\toptions: EnvironmentOptions,\n\tcommand: 'build' | 'serve',\n): EnvironmentOptions {\n\tconst added = bunEnvironment(options);\n\tconst bundled = command === 'build' ? bundledEnvironment(options) : undefined;\n\tif (bundled === undefined) return added;\n\treturn { ...added, resolve: { ...added.resolve, ...bundled.resolve } };\n}\n",
|
|
7
8
|
"/**\n * What the plugin reads of Vite's and React Router's config: the server\n * file, the client folder, and the server build's bundler options.\n */\nimport { existsSync } from 'node:fs';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\nimport type { ResolvedConfig } from 'vite';\nimport { NAME } from './entry';\n\n/** The server build's input, and in dev the module the requests go to. */\nexport const SERVER = 'virtual:alxia-react-router/server';\n/** The same, when there is no server file: `createServer()` as it is. */\nexport const DEFAULT = `${SERVER}-default`;\n\n/** What the plugin reads of React Router's own config. */\nexport interface ReactRouterConfig {\n\treadonly appDirectory: string;\n\treadonly buildDirectory: string;\n\treadonly serverBuildFile: string;\n\treadonly ssr: boolean;\n\treadonly serverBundles?: unknown;\n}\n\n/** React Router's config, which its plugin puts on Vite's. */\nexport function contextOf(config: object): ReactRouterConfig {\n\tconst context = (\n\t\tconfig as {\n\t\t\treadonly __reactRouterPluginContext?: {\n\t\t\t\treadonly reactRouterConfig: ReactRouterConfig;\n\t\t\t};\n\t\t}\n\t).__reactRouterPluginContext;\n\tif (context === undefined) {\n\t\tthrow new Error(\n\t\t\t`${NAME}: React Router's Vite plugin is not in this config. Add reactRouter() from @react-router/dev/vite beside alxia() in vite.config.ts.`,\n\t\t);\n\t}\n\treturn context.reactRouterConfig;\n}\n\n/** React Router's child compiler: a Vite server without its plugin, cached apart. */\nexport function isChildCompiler(config: ResolvedConfig): boolean {\n\treturn (\n\t\t(config as { readonly __reactRouterPluginContext?: unknown })\n\t\t\t.__reactRouterPluginContext === undefined &&\n\t\tconfig.cacheDir.endsWith('.vite-child-compiler')\n\t);\n}\n\n/**\n * The server file: `entry`, which must exist, or `app/server.ts` when it\n * does, or `undefined` for the default server.\n */\nexport function serverFile(\n\tentry: string | undefined,\n\tconfig: ResolvedConfig,\n): string | undefined {\n\tif (entry !== undefined) {\n\t\tconst file = isAbsolute(entry) ? entry : resolve(config.root, entry);\n\t\tif (!existsSync(file)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${NAME}: the entry ${entry} does not exist. Create it, or leave entry out to use app/server.ts, or the default server without it.`,\n\t\t\t);\n\t\t}\n\t\treturn file;\n\t}\n\tconst file = join(contextOf(config).appDirectory, 'server.ts');\n\treturn existsSync(file) ? file : undefined;\n}\n\n/** The built server, absolute: `build/server/index.js`. */\nexport function serverBuildPath(config: ResolvedConfig): string {\n\tconst rr = contextOf(config);\n\tconst outDir = resolve(\n\t\tconfig.root,\n\t\tconfig.environments['ssr']?.build.outDir ??\n\t\t\tjoin(rr.buildDirectory, 'server'),\n\t);\n\treturn join(outDir, rr.serverBuildFile);\n}\n\n/** `build/client`, relative to the built `build/server/index.js`. */\nexport function clientPath(config: ResolvedConfig): string {\n\tconst built = dirname(serverBuildPath(config));\n\tconst path = relative(\n\t\tbuilt,\n\t\tjoin(contextOf(config).buildDirectory, 'client'),\n\t);\n\treturn path.startsWith('.') ? path : `./${path}`;\n}\n\n/**\n * The ssr build's options: one file, `build/server/index.js`, the server\n * and React Router's build together. Rolldown, under Vite 8, names the\n * option otherwise.\n */\nexport function serverBuildOptions(rolldown: boolean): object {\n\treturn rolldown\n\t\t? {\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tinput: SERVER,\n\t\t\t\t\toutput: { codeSplitting: false },\n\t\t\t\t},\n\t\t\t}\n\t\t: {\n\t\t\t\trollupOptions: {\n\t\t\t\t\tinput: SERVER,\n\t\t\t\t\toutput: { inlineDynamicImports: true },\n\t\t\t\t},\n\t\t\t};\n}\n",
|
|
8
9
|
"/**\n * The few lines between Vite's dev and preview servers, which speak\n * `node:http`, and an alxia app, which speaks `Request` and `Response`: no\n * dependency, Bun's own `node:http` and `node:stream` underneath.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { Readable } from 'node:stream';\n\n/** What Connect, Vite's middleware stack, adds to a request: the URL before any rewrite. */\ntype ConnectRequest = IncomingMessage & {\n\treadonly originalUrl?: string | undefined;\n};\n\n/** The `Request` a Node request stands for. Aborted when the client goes away. */\nexport function toRequest(req: ConnectRequest, res: ServerResponse): Request {\n\tconst secure = (req.socket as { encrypted?: boolean }).encrypted === true;\n\tconst url = new URL(\n\t\treq.originalUrl ?? req.url ?? '/',\n\t\t`${secure ? 'https' : 'http'}://${req.headers.host ?? 'localhost'}`,\n\t);\n\tconst headers = new Headers();\n\tconst raw = req.rawHeaders;\n\tfor (let i = 0; i + 1 < raw.length; i += 2) {\n\t\tconst name = raw[i] as string;\n\t\t// HTTP/2's pseudo-headers (`:path`, `:method`) are not headers.\n\t\tif (!name.startsWith(':')) headers.append(name, raw[i + 1] as string);\n\t}\n\tconst controller = new AbortController();\n\tres.once('close', () => {\n\t\tif (!res.writableFinished) controller.abort();\n\t});\n\tconst method = req.method ?? 'GET';\n\tconst init: RequestInit & { duplex?: 'half' } = {\n\t\tmethod,\n\t\theaders,\n\t\tsignal: controller.signal,\n\t};\n\tif (method !== 'GET' && method !== 'HEAD') {\n\t\tinit.body = Readable.toWeb(req) as unknown as ReadableStream<Uint8Array>;\n\t\tinit.duplex = 'half';\n\t}\n\treturn new Request(url, init);\n}\n\n/** Writes `response` to `res`, streaming its body chunk by chunk as it comes. */\nexport async function send(\n\tres: ServerResponse,\n\tresponse: Response,\n): Promise<void> {\n\tres.statusCode = response.status;\n\tif (response.statusText !== '') res.statusMessage = response.statusText;\n\tfor (const [name, value] of response.headers) {\n\t\tif (name !== 'set-cookie') res.setHeader(name, value);\n\t}\n\tconst cookies = response.headers.getSetCookie();\n\tif (cookies.length > 0) res.setHeader('set-cookie', cookies);\n\tif (response.body === null) {\n\t\tres.end();\n\t\treturn;\n\t}\n\tres.flushHeaders();\n\tconst reader = response.body.getReader();\n\tconst cancel = () => void reader.cancel().catch(() => {});\n\tres.once('close', cancel);\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tif (res.destroyed) return;\n\t\t\tif (!res.write(value)) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tconst go = () => {\n\t\t\t\t\t\tres.off('drain', go);\n\t\t\t\t\t\tres.off('close', go);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t\tres.on('drain', go);\n\t\t\t\t\tres.on('close', go);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tres.end();\n\t} finally {\n\t\tres.off('close', cancel);\n\t}\n}\n",
|
|
9
10
|
"/**\n * Under `react-router dev` and `vite preview`: the app's WebSocket routes. Vite's server is a\n * `node:http` one, and an alxia socket is `Bun.serve`'s upgrade, so each\n * upgrade Vite leaves is relayed, bytes as they come, to a `Bun.serve` of\n * the app's own on a loopback port: its hooks, its validation, its socket\n * handlers, exactly as `listen` runs them.\n */\nimport type { IncomingMessage } from 'node:http';\nimport { connect, type Socket } from 'node:net';\nimport type { DevApp } from './dev';\nimport { NAME } from './entry';\n\n/** The subprotocols of Vite's own socket, the HMR one and its ping: Vite answers them. */\nconst VITE = new Set(['vite-hmr', 'vite-ping']);\n\n/** Whether the upgrade asks for Vite's own socket. */\nexport function isVites(req: Pick<IncomingMessage, 'headers'>): boolean {\n\tconst protocols = req.headers['sec-websocket-protocol'];\n\tif (protocols === undefined) return false;\n\treturn protocols.split(',').some((protocol) => VITE.has(protocol.trim()));\n}\n\n/** One entry of Vite's `server.proxy`, as far as its sockets go. */\ntype ProxyEntry = string | { readonly ws?: boolean; readonly target?: unknown };\n\n/**\n * Whether Vite's `server.proxy` relays this upgrade itself: an entry whose\n * context matches the URL, as Vite matches it (`^…` a RegExp, otherwise a\n * prefix), and that proxies sockets (`ws: true`, or a `ws:`/`wss:` target).\n */\nexport function isProxied(\n\turl: string,\n\tproxy: Readonly<Record<string, ProxyEntry>> | undefined,\n): boolean {\n\tfor (const [context, entry] of Object.entries(proxy ?? {})) {\n\t\tconst matches =\n\t\t\t(context.startsWith('^') && new RegExp(context).test(url)) ||\n\t\t\turl.startsWith(context);\n\t\tif (!matches) continue;\n\t\tconst options = typeof entry === 'string' ? { target: entry } : entry;\n\t\tconst target = String(options.target ?? '');\n\t\tif (\n\t\t\toptions.ws === true ||\n\t\t\ttarget.startsWith('ws:') ||\n\t\t\ttarget.startsWith('wss:')\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/** The request line and headers of `req`, as they came: what the side server reads. */\nexport function head(\n\treq: Pick<IncomingMessage, 'method' | 'url' | 'rawHeaders'>,\n): string {\n\tconst lines = [`${req.method ?? 'GET'} ${req.url ?? '/'} HTTP/1.1`];\n\tconst raw = req.rawHeaders;\n\tfor (let i = 0; i + 1 < raw.length; i += 2) {\n\t\tlines.push(`${raw[i]}: ${raw[i + 1]}`);\n\t}\n\treturn `${lines.join('\\r\\n')}\\r\\n\\r\\n`;\n}\n\n/** The side servers: the current app's, and those an edit retired, until their sockets close. */\nexport interface Sides {\n\tcurrent:\n\t\t| { readonly app: DevApp; readonly side: Bun.Server<unknown> }\n\t\t| undefined;\n\treadonly retired: Set<Bun.Server<unknown>>;\n}\n\n/**\n * The side server of `app`, started on its first upgrade. A new app, an\n * edit's, retires the previous one: no new connection, and the sockets open\n * on it stay, with the handlers they opened with, until they close.\n */\nexport function sideFor(sides: Sides, app: DevApp): Bun.Server<unknown> {\n\tif (sides.current?.app === app) return sides.current.side;\n\tconst side = Bun.serve({\n\t\tport: 0,\n\t\thostname: '127.0.0.1',\n\t\tfetch: (request, bun) => app.fetch(request, bun),\n\t\twebsocket: app.websocket,\n\t} as Bun.Serve.Options<never>) as Bun.Server<unknown>;\n\tconst old = sides.current?.side;\n\tif (old !== undefined) {\n\t\tsides.retired.add(old);\n\t\tvoid old.stop().then(() => sides.retired.delete(old));\n\t}\n\tsides.current = { app, side };\n\treturn side;\n}\n\n/** Stops every side server, open sockets and all: Vite's server closed. */\nexport function closeAll(sides: Sides): void {\n\tfor (const side of [...sides.retired, sides.current?.side]) {\n\t\tvoid side?.stop(true);\n\t}\n\tsides.current = undefined;\n\tsides.retired.clear();\n}\n\n/** Relays the upgrade on `socket` to the side server on `port`, both ways. */\nfunction relay(\n\treq: IncomingMessage,\n\tsocket: Socket,\n\tbytes: Buffer,\n\tport: number,\n): void {\n\tconst upstream = connect(port, '127.0.0.1', () => {\n\t\tupstream.write(head(req));\n\t\tif (bytes.length > 0) upstream.write(bytes);\n\t\tupstream.pipe(socket);\n\t\tsocket.pipe(upstream);\n\t});\n\tupstream.on('error', () => socket.destroy());\n\tupstream.on('close', () => socket.destroy());\n\tsocket.on('close', () => upstream.destroy());\n}\n\n/** What the relay listens to on Vite's HTTP server, HTTP/1 or HTTP/2 alike. */\ninterface Upgrades {\n\ton(\n\t\tevent: 'upgrade',\n\t\tlistener: (req: IncomingMessage, socket: Socket, bytes: Buffer) => void,\n\t): unknown;\n\tonce(event: 'close', listener: () => void): unknown;\n}\n\n/** What the relay needs of the server it listens on: Vite's dev server or its preview. */\nexport interface Bridge {\n\t/** Vite's `server.proxy` (or `preview.proxy`): the upgrades it relays are its own. */\n\treadonly proxy: Readonly<Record<string, ProxyEntry>> | undefined;\n\t/** The app, as it is now. */\n\treadonly load: () => Promise<DevApp>;\n\t/** Where an upgrade that failed is printed: Vite's logger. */\n\treadonly logger: { error(message: string): void };\n\t/** Maps an error's stack to the source, as Vite's `ssrFixStacktrace` does. */\n\treadonly fix?: (error: Error) => void;\n}\n\n/** An upgrade the app could not take: reported, and a 500 to the client. */\nfunction refuse(bridge: Bridge, socket: Socket, error: unknown): void {\n\tif (error instanceof Error) bridge.fix?.(error);\n\tbridge.logger.error(\n\t\t`${NAME}: a WebSocket upgrade failed: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`,\n\t);\n\tif (socket.writable) {\n\t\tsocket.end(\n\t\t\t'HTTP/1.1 500 Internal Server Error\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n',\n\t\t);\n\t}\n}\n\n/**\n * Relays the app's upgrades on Vite's HTTP server to a side server of the\n * app. Vite's own socket and the sockets its proxy relays are left to\n * Vite. Without an HTTP server (Vite's middleware mode), there is nothing\n * to listen on.\n */\nexport function bridgeSockets(http: Upgrades | null, bridge: Bridge): void {\n\tif (http === null) return;\n\tconst sides: Sides = { current: undefined, retired: new Set() };\n\thttp.on('upgrade', (req: IncomingMessage, socket: Socket, bytes: Buffer) => {\n\t\tif (isVites(req) || isProxied(req.url ?? '/', bridge.proxy)) return;\n\t\tsocket.on('error', () => socket.destroy());\n\t\tbridge\n\t\t\t.load()\n\t\t\t.then((app) => {\n\t\t\t\tif (socket.destroyed) return;\n\t\t\t\trelay(req, socket, bytes, sideFor(sides, app).port as number);\n\t\t\t})\n\t\t\t.catch((error: unknown) => refuse(bridge, socket, error));\n\t});\n\thttp.once('close', () => closeAll(sides));\n}\n",
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
"/**\n * Under `vite preview`, and React Router's prerendering, which runs on it:\n * every request goes to the built server, `build/server/index.js`'s\n * default export, as `bun build/server/index.js` would answer it — its\n * hooks, its `/api`, the client's files and the pages.\n */\nimport { existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { PreviewServer } from 'vite';\nimport { serverBuildPath } from './config';\nimport type { DevApp } from './dev';\nimport { NAME } from './entry';\nimport { send, toRequest } from './node';\nimport { bridgeSockets } from './socket';\n\n/** What the built server's default export is: the alxia app. */\ninterface Fetcher {\n\tfetch(request: Request): Response | Promise<Response>;\n}\n\n/** The built server's app, or an error saying why there is none. */\nasync function load(file: string, label: string): Promise<Fetcher> {\n\tif (!existsSync(file)) {\n\t\tthrow new Error(\n\t\t\t`${NAME}: ${label} does not exist. Run react-router build before vite preview.`,\n\t\t);\n\t}\n\tconst module = (await import(pathToFileURL(file).href)) as {\n\t\treadonly default?: Partial<Fetcher>;\n\t};\n\tif (typeof module.default?.fetch !== 'function') {\n\t\tthrow new Error(\n\t\t\t`${NAME}: ${label} is not alxia's server: its default export has no fetch. Build it with alxia() in vite.config.ts's plugins, then run vite preview again.`,\n\t\t);\n\t}\n\treturn module.default as Fetcher;\n}\n\n/**\n * Hands every request to the built server, before Vite's own files: the\n * app serves `build/client` itself, with its hooks and cache headers. Its\n * WebSocket routes connect too, relayed as under `react-router dev`.\n */\nexport function servePreview(server: PreviewServer): void {\n\tconst file = serverBuildPath(server.config);\n\tconst label = relative(server.config.root, file);\n\t// Loaded on the first request, as `bun build/server/index.js` would be\n\t// at startup; a failed load is tried again on the next, after a build.\n\tlet app: Promise<Fetcher> | undefined;\n\tconst current = (): Promise<Fetcher> => {\n\t\tapp ??= load(file, label);\n\t\treturn app;\n\t};\n\tbridgeSockets(server.httpServer, {\n\t\tproxy: server.config.preview.proxy,\n\t\t// The built server's default export is the alxia app, `websocket` and all.\n\t\tload: () =>\n\t\t\tcurrent().catch((error: unknown) => {\n\t\t\t\tapp = undefined;\n\t\t\t\tthrow error;\n\t\t\t}) as Promise<DevApp>,\n\t\tlogger: server.config.logger,\n\t});\n\tserver.middlewares.use((req, res, next) => {\n\t\tcurrent().then(\n\t\t\tasync (loaded) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait send(res, await loaded.fetch(toRequest(req, res)));\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Mid-body, the response has started: end it rather than answer twice.\n\t\t\t\t\tif (res.headersSent) res.destroy(error as Error);\n\t\t\t\t\telse next(error);\n\t\t\t\t}\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tapp = undefined;\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tserver.config.logger.error(message);\n\t\t\t\tres.statusCode = 500;\n\t\t\t\tres.setHeader('content-type', 'text/plain; charset=utf-8');\n\t\t\t\tres.end(message);\n\t\t\t},\n\t\t);\n\t});\n}\n",
|
|
12
13
|
"import { NAME } from './entry';\n\n/**\n * Refuses, with what to do, a dev or preview server running on Node. The\n * React Router CLI's `#!/usr/bin/env node` runs it on Node whenever a node\n * is installed, even from `bun run dev`, and alxia's server then fails on\n * its first request with `ReferenceError: Bun is not defined`.\n */\nexport function requireBun(\n\tcommand: string,\n\thint = `bun --bun ${command}`,\n\tonBun = (globalThis as { Bun?: unknown }).Bun !== undefined,\n): void {\n\tif (onBun) return;\n\tthrow new Error(\n\t\t`${NAME}: ${command} is running on Node, and alxia's server runs on Bun. Add a bunfig.toml beside package.json with \"[run]\" and \"bun = true\", so bun run starts it on Bun, or run it as ${hint}.`,\n\t);\n}\n"
|
|
13
14
|
],
|
|
14
|
-
"mappings": "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",
|
|
15
|
-
"debugId": "
|
|
15
|
+
"mappings": "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",
|
|
16
|
+
"debugId": "68EB80E9F1CC79CC64756E2164756E21",
|
|
16
17
|
"names": []
|
|
17
18
|
}
|
package/docs/guide.md
CHANGED
|
@@ -154,6 +154,10 @@ server build inside it, into one file:
|
|
|
154
154
|
- **The client folder is resolved against the built file**: `../client`,
|
|
155
155
|
from React Router's `buildDirectory`, so it is found wherever the
|
|
156
156
|
process starts.
|
|
157
|
+
- **It is self-contained**: every package the server imports, React,
|
|
158
|
+
React Router and alxia included, is bundled into it
|
|
159
|
+
([Self-contained](#self-contained)), so `build/` runs with no
|
|
160
|
+
`node_modules`.
|
|
157
161
|
|
|
158
162
|
```sh
|
|
159
163
|
bun run build
|
|
@@ -214,14 +218,16 @@ and `configure`'s hooks run around it.
|
|
|
214
218
|
|
|
215
219
|
`build/server/index.js` runs on Bun, and the plugin builds it for Bun,
|
|
216
220
|
with nothing to configure. It adds to Vite's `ssr` environment, under
|
|
217
|
-
`react-router dev` and `react-router build` alike
|
|
221
|
+
`react-router dev` and `react-router build` alike but for the last row,
|
|
222
|
+
the build's alone:
|
|
218
223
|
|
|
219
224
|
| option | what the plugin adds | why |
|
|
220
225
|
| --- | --- | --- |
|
|
221
226
|
| `resolve.conditions` | `bun` | a package bundled into the server whose `exports` has a `bun` condition is bundled as its Bun variant |
|
|
222
|
-
| `resolve.externalConditions` | `bun` | a dependency left external is loaded as its Bun variant
|
|
227
|
+
| `resolve.externalConditions` | `bun` | a dependency left external, as every one is in dev and one the app names in `ssr.external` is in the build, is loaded as its Bun variant, as Bun loads it |
|
|
223
228
|
| `resolve.builtins` | `bun`, and `bun:*` (`bun:sqlite`, `bun:ffi`, …) | Bun's own modules stay imports of the build, whichever runtime runs Vite. Vite knows `bun:*`, and bare `bun` only when it runs on Bun |
|
|
224
229
|
| `build.target` | `esnext` | the newest syntax is left as written: Bun runs it, and Vite's default targets browsers |
|
|
230
|
+
| `resolve.noExternal` | `true`, under `react-router build` only | every package is bundled into `build/server/index.js`, so `build/` runs with no `node_modules` ([Self-contained](#self-contained)) |
|
|
225
231
|
|
|
226
232
|
A package written for Bun, then, gives the build the variant Bun would
|
|
227
233
|
load, and Bun's own modules are used as they are:
|
|
@@ -293,6 +299,60 @@ export default defineConfig({
|
|
|
293
299
|
`ssr.resolve.conditions` at the top level is the same option, and is kept
|
|
294
300
|
the same way.
|
|
295
301
|
|
|
302
|
+
### Self-contained
|
|
303
|
+
|
|
304
|
+
Under `react-router build`, the plugin sets `resolve.noExternal: true` on
|
|
305
|
+
the `ssr` environment: Vite bundles every package the server imports into
|
|
306
|
+
`build/server/index.js`, where it would otherwise leave each one under
|
|
307
|
+
`node_modules` as an `import`. What the file still imports is Node's and
|
|
308
|
+
Bun's own modules:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
// build/server/index.js, its imports
|
|
312
|
+
import { createRequire } from "node:module";
|
|
313
|
+
import { PassThrough } from "node:stream";
|
|
314
|
+
// … and no "react", "react-router" or "@alxia/core"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
So `build/` is all a server needs, beside Bun: a Docker image's last
|
|
318
|
+
stage copies it alone ([Docker](#docker)). React and `react-dom/server`,
|
|
319
|
+
React Router, alxia and its plugins bundle as they are, CommonJS included;
|
|
320
|
+
the `bun` condition above picks each package's Bun variant. One copy of
|
|
321
|
+
each package is in the file, so `alxiaContext` and the app's own keys are
|
|
322
|
+
one object for the server and the routes. React Router's prerendering and
|
|
323
|
+
`vite preview` load the same file.
|
|
324
|
+
|
|
325
|
+
`react-router dev` is left as it was: Vite's SSR runner loads the
|
|
326
|
+
packages from `node_modules`.
|
|
327
|
+
|
|
328
|
+
What the app sets wins. Vite reads `external` before `noExternal`:
|
|
329
|
+
|
|
330
|
+
- **`ssr.external: ['sharp']`**, or the same on
|
|
331
|
+
`environments.ssr.resolve.external`, keeps those packages external,
|
|
332
|
+
imported from `node_modules` at runtime. Use it for a package that
|
|
333
|
+
cannot be bundled: a native addon (a `.node` file), or one that reads
|
|
334
|
+
files of its own folder at runtime. The image must then hold that
|
|
335
|
+
package ([Docker](#docker)).
|
|
336
|
+
- **`ssr.external: true`** keeps every package external, Vite's own
|
|
337
|
+
behaviour: the plugin adds no `noExternal` then, and the server needs
|
|
338
|
+
the production `node_modules` beside `build/`.
|
|
339
|
+
- **`ssr.noExternal`**, a list, changes nothing: everything is bundled
|
|
340
|
+
already.
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
// vite.config.ts
|
|
344
|
+
export default defineConfig({
|
|
345
|
+
// Bundled but for sharp, a native addon.
|
|
346
|
+
ssr: { external: ['sharp'] },
|
|
347
|
+
plugins: [reactRouter(), alxia()],
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
A package the build could not bundle and was not told to leave external
|
|
352
|
+
fails at runtime, from `build/` alone, with Bun's
|
|
353
|
+
`Cannot find package '…'`: see
|
|
354
|
+
[the troubleshooting entry](troubleshooting.md#error-cannot-find-package--from-appbuildserverindexjs).
|
|
355
|
+
|
|
296
356
|
## Customising the server
|
|
297
357
|
|
|
298
358
|
Write `app/server.ts`, with `createServer()` as its default export, or let
|
|
@@ -1013,9 +1073,10 @@ is `POST /?index`, not `POST /`.
|
|
|
1013
1073
|
|
|
1014
1074
|
## Deploying
|
|
1015
1075
|
|
|
1016
|
-
Run `bun run build`, then `bun build/server/index.js
|
|
1017
|
-
|
|
1018
|
-
|
|
1076
|
+
Run `bun run build`, then `bun build/server/index.js`. The build is
|
|
1077
|
+
[self-contained](#self-contained): `build/` is all the server needs, with
|
|
1078
|
+
no `node_modules`, unless the app keeps a package external with
|
|
1079
|
+
`ssr.external`.
|
|
1019
1080
|
|
|
1020
1081
|
### Docker
|
|
1021
1082
|
|
|
@@ -1027,14 +1088,10 @@ ship this `Dockerfile`, on Bun's official image. For an app started from
|
|
|
1027
1088
|
on Node:
|
|
1028
1089
|
|
|
1029
1090
|
```dockerfile
|
|
1030
|
-
# Bun builds the app and
|
|
1031
|
-
#
|
|
1032
|
-
|
|
1033
|
-
#
|
|
1034
|
-
FROM oven/bun:1 AS production-dependencies
|
|
1035
|
-
WORKDIR /app
|
|
1036
|
-
COPY package.json bun.lock* bunfig.toml* ./
|
|
1037
|
-
RUN bun install --frozen-lockfile --production
|
|
1091
|
+
# Bun builds the app, and the image holds build/ alone: alxia's plugin
|
|
1092
|
+
# bundles every dependency into build/server/index.js, alxia's server, which
|
|
1093
|
+
# runs on Bun with no node_modules. Pinned to Bun 1, the major alxia
|
|
1094
|
+
# supports.
|
|
1038
1095
|
|
|
1039
1096
|
# Every dependency, then react-router build: build/client and
|
|
1040
1097
|
# build/server/index.js.
|
|
@@ -1045,17 +1102,18 @@ RUN bun install --frozen-lockfile
|
|
|
1045
1102
|
COPY . .
|
|
1046
1103
|
RUN bun run build
|
|
1047
1104
|
|
|
1048
|
-
# The build
|
|
1049
|
-
#
|
|
1105
|
+
# The build, run as Bun's own non-root user with the start script's
|
|
1106
|
+
# command, and --no-install: with no node_modules, Bun would otherwise
|
|
1107
|
+
# fetch a package the build left out from the registry at startup,
|
|
1108
|
+
# where this fails.
|
|
1109
|
+
# The server listens on PORT (3000) and HOST (0.0.0.0).
|
|
1050
1110
|
FROM oven/bun:1
|
|
1051
1111
|
WORKDIR /app
|
|
1052
1112
|
ENV NODE_ENV=production
|
|
1053
|
-
COPY package.json ./
|
|
1054
|
-
COPY --from=production-dependencies /app/node_modules ./node_modules
|
|
1055
1113
|
COPY --from=build /app/build ./build
|
|
1056
1114
|
USER bun
|
|
1057
1115
|
EXPOSE 3000
|
|
1058
|
-
CMD ["bun", "build/server/index.js"]
|
|
1116
|
+
CMD ["bun", "--no-install", "build/server/index.js"]
|
|
1059
1117
|
```
|
|
1060
1118
|
|
|
1061
1119
|
```sh
|
|
@@ -1067,7 +1125,9 @@ Keep the template's `.dockerignore` beside it: `node_modules`, `build` and
|
|
|
1067
1125
|
`.react-router` stay out of the context, so the image installs and builds
|
|
1068
1126
|
its own. The `bunfig.toml` goes in, and `bun run build` runs React
|
|
1069
1127
|
Router's CLI on Bun, as it does outside Docker. The image's command is
|
|
1070
|
-
`start`'s, run directly, so the platform's `SIGTERM` reaches the server
|
|
1128
|
+
`start`'s, run directly, so the platform's `SIGTERM` reaches the server,
|
|
1129
|
+
with `--no-install`: a package missing from `build/` then fails at
|
|
1130
|
+
startup, where Bun would otherwise fetch it from npm.
|
|
1071
1131
|
|
|
1072
1132
|
- **Commit `bun.lock`.** The installs are `--frozen-lockfile`: the image
|
|
1073
1133
|
gets the versions you tested, and a `package.json` changed without a
|
|
@@ -1076,6 +1136,25 @@ Router's CLI on Bun, as it does outside Docker. The image's command is
|
|
|
1076
1136
|
- **The server runs as `bun`**, a user with no write access to `/app`.
|
|
1077
1137
|
Write files to a volume the user owns
|
|
1078
1138
|
([troubleshooting](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/troubleshooting.md#eacces-permission-denied-open-app)).
|
|
1139
|
+
- **The image holds `build/` alone**, no `node_modules`: the build is
|
|
1140
|
+
[self-contained](#self-contained). An app that keeps a package external
|
|
1141
|
+
with `ssr.external` copies the production dependencies too, from a
|
|
1142
|
+
stage of their own:
|
|
1143
|
+
|
|
1144
|
+
```dockerfile
|
|
1145
|
+
# Before the build stage: the production dependencies alone.
|
|
1146
|
+
FROM oven/bun:1 AS production-dependencies
|
|
1147
|
+
WORKDIR /app
|
|
1148
|
+
COPY package.json bun.lock* bunfig.toml* ./
|
|
1149
|
+
RUN bun install --frozen-lockfile --production
|
|
1150
|
+
|
|
1151
|
+
# In the final stage, beside build/.
|
|
1152
|
+
COPY --from=production-dependencies /app/node_modules ./node_modules
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
Without it, the container stops at startup with
|
|
1156
|
+
`Cannot find package '…'`
|
|
1157
|
+
([troubleshooting](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/troubleshooting.md#error-cannot-find-package--from-appbuildserverindexjs)).
|
|
1079
1158
|
|
|
1080
1159
|
`PORT` and `HOST` set where the server listens. The platform's `SIGTERM`
|
|
1081
1160
|
stops it once the requests in flight are answered, and runs the app's
|
package/docs/roadmap.md
CHANGED
|
@@ -47,6 +47,11 @@ Nothing scheduled yet.
|
|
|
47
47
|
|
|
48
48
|
### Next release
|
|
49
49
|
|
|
50
|
+
- **A self-contained build.** `react-router build` bundles every package
|
|
51
|
+
into `build/server/index.js`, React, React Router and alxia included,
|
|
52
|
+
so `build/` runs with no `node_modules` and a Docker image copies it
|
|
53
|
+
alone. Never in dev; `ssr.external` keeps a package external, and
|
|
54
|
+
`ssr.external: true` every package.
|
|
50
55
|
- **The server is built for Bun.** `alxia()` adds the `bun` export
|
|
51
56
|
condition to the `ssr` environment's conditions and external
|
|
52
57
|
conditions, keeps `bun` and `bun:*` external whichever runtime runs
|
|
@@ -55,7 +60,8 @@ Nothing scheduled yet.
|
|
|
55
60
|
app sets is kept.
|
|
56
61
|
- **A Docker image on Bun.** The guide's Deploying has the multi-stage
|
|
57
62
|
`Dockerfile` on `oven/bun:1` that `@alxia/create`'s template and the
|
|
58
|
-
example ship, running `bun build/server/index.js` as a non-root user
|
|
63
|
+
example ship, running `bun build/server/index.js` as a non-root user,
|
|
64
|
+
from `build/` alone.
|
|
59
65
|
- **A per-request CSP nonce.** `nonceOf(loadContext)` reads the nonce that
|
|
60
66
|
`@alxia/secure-headers`' `nonce: true`, or a `derive` of the app's own,
|
|
61
67
|
put on the context, so `entry.server.tsx` hands it to `<ServerRouter
|
package/docs/troubleshooting.md
CHANGED
|
@@ -36,6 +36,7 @@ a loader, a message React Router or the browser prints, or an error from
|
|
|
36
36
|
- [`Module "…" has been externalized for browser compatibility, imported by "…"`](#module--has-been-externalized-for-browser-compatibility-imported-by-)
|
|
37
37
|
- [`error: lockfile had changes, but lockfile is frozen`](#error-lockfile-had-changes-but-lockfile-is-frozen)
|
|
38
38
|
- [`EACCES: permission denied, open '/app/…'`](#eacces-permission-denied-open-app)
|
|
39
|
+
- [`error: Cannot find package '…' from '/app/build/server/index.js'`](#error-cannot-find-package--from-appbuildserverindexjs)
|
|
39
40
|
|
|
40
41
|
**Types**
|
|
41
42
|
|
|
@@ -675,6 +676,57 @@ VOLUME /data
|
|
|
675
676
|
const db = new Database('/data/app.sqlite');
|
|
676
677
|
```
|
|
677
678
|
|
|
679
|
+
### `error: Cannot find package '…' from '/app/build/server/index.js'`
|
|
680
|
+
|
|
681
|
+
`bun build/server/index.js`, in the container or from a copy of `build/`
|
|
682
|
+
alone, stops at startup. For a package loaded with `require`, the message
|
|
683
|
+
can read `Cannot find module '…'`. Or it starts, and a request fails with
|
|
684
|
+
`ENOENT: no such file or directory, open '/app/build/…'`.
|
|
685
|
+
|
|
686
|
+
**When:** the image holds `build/` alone, as the template's `Dockerfile`
|
|
687
|
+
copies it, and the server imports a package that is not inside
|
|
688
|
+
`build/server/index.js`:
|
|
689
|
+
|
|
690
|
+
- the app keeps it external with `ssr.external`, and the image has no
|
|
691
|
+
`node_modules`;
|
|
692
|
+
- or the build bundled it, but it reads a file of its own folder at
|
|
693
|
+
runtime (`new URL('./data.json', import.meta.url)`), or loads a native
|
|
694
|
+
addon (a `.node` file), neither of which bundling carries along.
|
|
695
|
+
|
|
696
|
+
The image runs `bun --no-install`: without the flag, Bun finds no
|
|
697
|
+
`node_modules` and fetches the missing package from npm at startup, at
|
|
698
|
+
whatever version npm has, instead of failing.
|
|
699
|
+
|
|
700
|
+
**Why:** under `react-router build` the plugin bundles every package into
|
|
701
|
+
`build/server/index.js` ([Self-contained](guide.md#self-contained)), so
|
|
702
|
+
the image needs no `node_modules`. What stays outside the file must be
|
|
703
|
+
installed beside it.
|
|
704
|
+
|
|
705
|
+
**Fix:** keep the package external, and give the image the production
|
|
706
|
+
dependencies:
|
|
707
|
+
|
|
708
|
+
```ts
|
|
709
|
+
// vite.config.ts
|
|
710
|
+
export default defineConfig({
|
|
711
|
+
ssr: { external: ['sharp'] },
|
|
712
|
+
plugins: [reactRouter(), alxia()],
|
|
713
|
+
});
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
```dockerfile
|
|
717
|
+
# Dockerfile, before the build stage
|
|
718
|
+
FROM oven/bun:1 AS production-dependencies
|
|
719
|
+
WORKDIR /app
|
|
720
|
+
COPY package.json bun.lock* bunfig.toml* ./
|
|
721
|
+
RUN bun install --frozen-lockfile --production
|
|
722
|
+
|
|
723
|
+
# Dockerfile, in the final stage, beside build/
|
|
724
|
+
COPY --from=production-dependencies /app/node_modules ./node_modules
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
`grep '^import' build/server/index.js` lists what the build still
|
|
728
|
+
imports: `node:*`, `bun`, `bun:*` and the packages `ssr.external` names.
|
|
729
|
+
|
|
678
730
|
## Types
|
|
679
731
|
|
|
680
732
|
### `Property '…' does not exist on type 'BaseContext & …'`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alxia/react-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "alxia as the server of a React Router framework app: server rendering behind the app's hooks, loaders reading its typed context, the client's assets served",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|