@nifrajs/web 0.1.0-alpha.1
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 +18 -0
- package/css-modules.d.ts +34 -0
- package/dist/build.d.ts +110 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +238 -0
- package/dist/build.js.map +1 -0
- package/dist/client.d.ts +32 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +204 -0
- package/dist/client.js.map +1 -0
- package/dist/deferred.d.ts +90 -0
- package/dist/deferred.d.ts.map +1 -0
- package/dist/deferred.js +310 -0
- package/dist/deferred.js.map +1 -0
- package/dist/dev-error.d.ts +17 -0
- package/dist/dev-error.d.ts.map +1 -0
- package/dist/dev-error.js +59 -0
- package/dist/dev-error.js.map +1 -0
- package/dist/dev.d.ts +25 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +83 -0
- package/dist/dev.js.map +1 -0
- package/dist/draft.d.ts +58 -0
- package/dist/draft.d.ts.map +1 -0
- package/dist/draft.js +55 -0
- package/dist/draft.js.map +1 -0
- package/dist/fonts-google.d.ts +109 -0
- package/dist/fonts-google.d.ts.map +1 -0
- package/dist/fonts-google.js +291 -0
- package/dist/fonts-google.js.map +1 -0
- package/dist/fonts.d.ts +67 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +103 -0
- package/dist/fonts.js.map +1 -0
- package/dist/fs.d.ts +10 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +24 -0
- package/dist/fs.js.map +1 -0
- package/dist/index.d.ts +280 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +784 -0
- package/dist/index.js.map +1 -0
- package/dist/islands.d.ts +37 -0
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +107 -0
- package/dist/islands.js.map +1 -0
- package/dist/isr.d.ts +154 -0
- package/dist/isr.d.ts.map +1 -0
- package/dist/isr.js +331 -0
- package/dist/isr.js.map +1 -0
- package/dist/manifest.d.ts +178 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +213 -0
- package/dist/manifest.js.map +1 -0
- package/dist/plugins/css-modules.d.ts +40 -0
- package/dist/plugins/css-modules.d.ts.map +1 -0
- package/dist/plugins/css-modules.js +0 -0
- package/dist/plugins/css-modules.js.map +1 -0
- package/dist/plugins/kit.d.ts +44 -0
- package/dist/plugins/kit.d.ts.map +1 -0
- package/dist/plugins/kit.js +105 -0
- package/dist/plugins/kit.js.map +1 -0
- package/dist/plugins/scss.d.ts +27 -0
- package/dist/plugins/scss.d.ts.map +1 -0
- package/dist/plugins/scss.js +78 -0
- package/dist/plugins/scss.js.map +1 -0
- package/dist/prerender.d.ts +77 -0
- package/dist/prerender.d.ts.map +1 -0
- package/dist/prerender.js +139 -0
- package/dist/prerender.js.map +1 -0
- package/dist/query.d.ts +62 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +184 -0
- package/dist/query.js.map +1 -0
- package/dist/router.d.ts +169 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +531 -0
- package/dist/router.js.map +1 -0
- package/dist/vite.d.ts +49 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +144 -0
- package/dist/vite.js.map +1 -0
- package/package.json +127 -0
- package/src/build.ts +375 -0
- package/src/client.ts +218 -0
- package/src/deferred.ts +339 -0
- package/src/dev-error.ts +62 -0
- package/src/dev.ts +108 -0
- package/src/draft.ts +82 -0
- package/src/fonts-google.ts +397 -0
- package/src/fonts.ts +147 -0
- package/src/fs.ts +26 -0
- package/src/index.ts +1202 -0
- package/src/islands.ts +121 -0
- package/src/isr.ts +461 -0
- package/src/manifest.ts +366 -0
- package/src/plugins/css-modules.ts +0 -0
- package/src/plugins/kit.ts +123 -0
- package/src/plugins/scss.ts +108 -0
- package/src/prerender.ts +209 -0
- package/src/query.ts +250 -0
- package/src/router.ts +676 -0
- package/src/vite.ts +212 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nifra Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @nifrajs/web
|
|
2
|
+
|
|
3
|
+
Framework-agnostic SSR core for nifra — the render seam + HTML document orchestration.
|
|
4
|
+
|
|
5
|
+
Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework — one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
bun add @nifrajs/web
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Docs
|
|
14
|
+
|
|
15
|
+
- Reference: <https://nifra.dev/docs>
|
|
16
|
+
- AI-readable: <https://nifra.dev/llms.txt>
|
|
17
|
+
|
|
18
|
+
MIT
|
package/css-modules.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient types for CSS asset imports handled by the `@nifrajs/web/plugins/*` Bun plugins
|
|
3
|
+
* (`css-modules` + `scss`).
|
|
4
|
+
*
|
|
5
|
+
* Add to your app so the imports below are typed. Either reference it from a `.d.ts` in your project:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* /// <reference types="@nifrajs/web/css-modules" />
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* or list it in `tsconfig.json` → `compilerOptions.types: ["@nifrajs/web/css-modules"]`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** CSS Modules (`*.module.css`) → the scoped `{ originalClassName: scopedClassName }` map. */
|
|
15
|
+
declare module "*.module.css" {
|
|
16
|
+
/** Keys are the source class names (asIs convention). */
|
|
17
|
+
const classes: Readonly<Record<string, string>>
|
|
18
|
+
export default classes
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** SCSS/SASS Modules (`*.module.scss` / `*.module.sass`) → the scoped class map (same as above). */
|
|
22
|
+
declare module "*.module.scss" {
|
|
23
|
+
const classes: Readonly<Record<string, string>>
|
|
24
|
+
export default classes
|
|
25
|
+
}
|
|
26
|
+
declare module "*.module.sass" {
|
|
27
|
+
const classes: Readonly<Record<string, string>>
|
|
28
|
+
export default classes
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Plain stylesheet imports are side-effect only (`import "./styles.scss"`); they bundle the CSS and
|
|
32
|
+
// expose no bindings. Declared so the import resolves under TypeScript.
|
|
33
|
+
declare module "*.scss" {}
|
|
34
|
+
declare module "*.sass" {}
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { BunPlugin } from "bun";
|
|
2
|
+
export { type CloudflarePagesRoutes, type CloudflarePagesRoutesOptions, cloudflarePagesRoutes, dataFileFor, htmlFileFor, type PrerenderApp, type PrerenderEntry, type PrerenderOptions, type PrerenderResult, prerenderRoutes, } from "./prerender.js";
|
|
3
|
+
export interface BuildClientOptions {
|
|
4
|
+
/** The `routes/` directory to discover (absolute path). */
|
|
5
|
+
readonly routesDir: string;
|
|
6
|
+
/** Output directory for the bundle + `manifest.json` (absolute path). */
|
|
7
|
+
readonly outDir: string;
|
|
8
|
+
/** The adapter's client runtime (exports `mountRouter`), e.g. `"@nifrajs/web-solid/client"`. */
|
|
9
|
+
readonly clientModule: string;
|
|
10
|
+
/** Route/layout file → import specifier (default: `${routesDir}/${file}`). */
|
|
11
|
+
readonly resolve?: (file: string) => string;
|
|
12
|
+
/** Adapter build plugins (e.g. `solidBunPlugin("dom")`). */
|
|
13
|
+
readonly plugins?: readonly BunPlugin[];
|
|
14
|
+
/** `Bun.build` export conditions (e.g. `["bun", "solid", "browser"]`). */
|
|
15
|
+
readonly conditions?: readonly string[];
|
|
16
|
+
/** Compile-time replacements (e.g. `{ "process.env.NODE_ENV": '"production"' }`). */
|
|
17
|
+
readonly define?: Readonly<Record<string, string>>;
|
|
18
|
+
/** Minify the output (default `true`). */
|
|
19
|
+
readonly minify?: boolean;
|
|
20
|
+
/** URL prefix the assets are served under (default `"/assets/"`); also Bun's chunk `publicPath`. */
|
|
21
|
+
readonly publicPath?: string;
|
|
22
|
+
}
|
|
23
|
+
/** The built asset map — the server reads `entry` for the client script + serves `assets`. */
|
|
24
|
+
export interface BuildManifest {
|
|
25
|
+
/** URL of the client entry module (content-hashed). */
|
|
26
|
+
readonly entry: string;
|
|
27
|
+
/** URLs of every emitted asset (entry + chunks) — for serving + preloading. */
|
|
28
|
+
readonly assets: readonly string[];
|
|
29
|
+
/** `routeId → [layout chunk URLs…, own chunk URL]` — the chunks a route needs, for `createWebApp`'s
|
|
30
|
+
* `routePreload` (`<link rel="modulepreload">` the matched route alongside the entry). Each route +
|
|
31
|
+
* layout is also a build entrypoint, so it gets a named chunk the bootstrap's lazy import dedupes to. */
|
|
32
|
+
readonly routes: Readonly<Record<string, readonly string[]>>;
|
|
33
|
+
/** The app's bundled, content-hashed stylesheet(s) — the bootstrap's **aggregate** CSS (every
|
|
34
|
+
* `import './x.css'` reachable from the app). The complete stylesheet regardless of which file
|
|
35
|
+
* imported the CSS; the always-safe fallback `createWebApp` links when a route has no per-route entry
|
|
36
|
+
* in {@link routeStyles}. Omitted when the app imports no CSS. */
|
|
37
|
+
readonly css?: readonly string[];
|
|
38
|
+
/** `routeId → [chain CSS URLs]` — only the stylesheets the matched route's layout chain + own file
|
|
39
|
+
* actually use (Bun emits a per-entrypoint CSS bundle per route/layout, with shared-component CSS
|
|
40
|
+
* inlined into each consumer). `createWebApp` links these instead of the aggregate, so a page ships
|
|
41
|
+
* only its own CSS. A route is omitted (→ aggregate fallback) when its `[name]` collides with another
|
|
42
|
+
* route's basename (ambiguous CSS↔route) or the build emitted orphan shared-chunk CSS — correctness
|
|
43
|
+
* over minimality. Absent entirely when the app imports no CSS. */
|
|
44
|
+
readonly routeStyles?: Readonly<Record<string, readonly string[]>>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build the client bundle for a file-routed app. Writes the hashed assets + `manifest.json` to
|
|
48
|
+
* `outDir` and returns the manifest. Throws (with the bundler logs) on build failure — never
|
|
49
|
+
* silently ships a broken bundle.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildClient(options: BuildClientOptions): Promise<BuildManifest>;
|
|
52
|
+
export interface BuildServerOptions {
|
|
53
|
+
/** The `routes/` directory to discover (absolute path). */
|
|
54
|
+
readonly routesDir: string;
|
|
55
|
+
/** The worker entry module (absolute path) — your `worker.ts`. It imports `{ manifest, clientEntry }`
|
|
56
|
+
* from the generated `./server-manifest`, builds `createWebApp`, and `export default toFetchHandler(app)`. */
|
|
57
|
+
readonly serverEntry: string;
|
|
58
|
+
/** Output directory for the bundled worker (absolute path). */
|
|
59
|
+
readonly outDir: string;
|
|
60
|
+
/** The content-hashed client entry URL (from `buildClient`'s manifest) — **baked** into the generated
|
|
61
|
+
* server manifest, since a disk-less worker can't read `manifest.json` at runtime. */
|
|
62
|
+
readonly clientEntry: string;
|
|
63
|
+
/** Route/layout file → import specifier in the generated manifest (default: a relative path from the
|
|
64
|
+
* manifest's location — written next to `serverEntry` — to `routesDir`). */
|
|
65
|
+
readonly resolve?: (file: string) => string;
|
|
66
|
+
/** Filename for the generated server-manifest module, written next to `serverEntry` (default
|
|
67
|
+
* `"server-manifest.ts"`); your `serverEntry` imports it as `./server-manifest`. */
|
|
68
|
+
readonly manifestFile?: string;
|
|
69
|
+
/** Adapter build plugins (e.g. `solidBunPlugin("ssr")` — Solid routes need their SSR transform at
|
|
70
|
+
* build time; React's JSX is Bun-native and needs none). */
|
|
71
|
+
readonly plugins?: readonly BunPlugin[];
|
|
72
|
+
/** `Bun.build` resolution conditions (default `["workerd", "edge-light", "browser"]`) — selects each
|
|
73
|
+
* dependency's edge build. */
|
|
74
|
+
readonly conditions?: readonly string[];
|
|
75
|
+
/** Compile-time replacements (default `{ "process.env.NODE_ENV": '"production"' }` → production
|
|
76
|
+
* React/Solid on the edge). Pass an explicit object to override (e.g. `{}` to opt out). */
|
|
77
|
+
readonly define?: Readonly<Record<string, string>>;
|
|
78
|
+
/** Minify the output (default `true`). */
|
|
79
|
+
readonly minify?: boolean;
|
|
80
|
+
/** `Bun.build` target (default `"browser"` — the right shape for edge runtimes: Cloudflare Workers,
|
|
81
|
+
* Vercel Edge, Deno, Deno Deploy). Use `"node"` for a `@nifrajs/node` server (so `node:*` built-ins
|
|
82
|
+
* stay external), or `"bun"` for a Bun server. The default `conditions` + the edge resolve shims
|
|
83
|
+
* only apply to the `"browser"` target; `"node"`/`"bun"` resolve their own renderer builds via the
|
|
84
|
+
* matching condition. */
|
|
85
|
+
readonly target?: "browser" | "node" | "bun";
|
|
86
|
+
/** **Lazy/code-split routes** (default `false`): emit `() => import(route)` loaders + bundle with
|
|
87
|
+
* `splitting`, so each route is its own chunk loaded on first request (smaller cold-start parse)
|
|
88
|
+
* instead of all parsed at boot. The output becomes the worker entry **+ chunk files** in `outDir`
|
|
89
|
+
* — on Cloudflare, ship them with wrangler's `no_bundle` + `find_additional_modules` + an ESModule
|
|
90
|
+
* `rule` (Node/Deno import the chunks natively). Eager (one self-contained file) stays the default. */
|
|
91
|
+
readonly lazy?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** The built worker bundle — point your `wrangler.toml`'s `main` at `worker`. */
|
|
94
|
+
export interface ServerBuild {
|
|
95
|
+
/** Path to the bundled, self-contained worker entry. */
|
|
96
|
+
readonly worker: string;
|
|
97
|
+
/** Paths of every emitted output (entry + any code-split chunks) — what to ship to the platform. */
|
|
98
|
+
readonly outputs: readonly string[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build a self-contained **worker bundle** for a file-routed app on a disk-less edge (Cloudflare
|
|
102
|
+
* Workers / workerd). Discovers routes (build-time fs), codegens the static-import server manifest
|
|
103
|
+
* (`generateServerManifest`, written next to `serverEntry`), then bundles `serverEntry` with
|
|
104
|
+
* `Bun.build` using **edge conditions** + the adapter's SSR plugins. The output imports no `node:fs`
|
|
105
|
+
* and does no dynamic-path import, so it runs on workerd: point `wrangler.toml`'s `main` at it and
|
|
106
|
+
* serve the client assets via Workers Assets. Throws (with the bundler logs) on failure — never
|
|
107
|
+
* silently ships a broken worker.
|
|
108
|
+
*/
|
|
109
|
+
export declare function buildServer(options: BuildServerOptions): Promise<ServerBuild>;
|
|
110
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web/build` — the production build (Bun-only, build-time). `buildClient` codegens + bundles
|
|
3
|
+
* the client entry (content-hashed, code-split); `buildServer` codegens the static-import server
|
|
4
|
+
* manifest + bundles a self-contained **worker** for the disk-less edge (Cloudflare Workers). Both
|
|
5
|
+
* are Bun-specific and never on the request path (own subpath, like `@nifrajs/web/fs`); the *output*
|
|
6
|
+
* runs on any runtime.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { dirname, relative, resolve as resolvePath } from "node:path";
|
|
10
|
+
import { discoverRoutes } from "./fs.js";
|
|
11
|
+
import { generateClientEntry, generateServerManifest } from "./index.js";
|
|
12
|
+
// Build-time SSG: prerender opted-in static + dynamic routes to `index.html` (+ static `_data.json`),
|
|
13
|
+
// run after `buildClient`.
|
|
14
|
+
export { cloudflarePagesRoutes, dataFileFor, htmlFileFor, prerenderRoutes, } from "./prerender.js";
|
|
15
|
+
const basename = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
16
|
+
/** `[name]` Bun derives for an entrypoint: basename without extension (`users/[id].tsx` → `[id]`). */
|
|
17
|
+
const entryName = (file) => {
|
|
18
|
+
const base = basename(file);
|
|
19
|
+
const dot = base.lastIndexOf(".");
|
|
20
|
+
return dot === -1 ? base : base.slice(0, dot);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Build the client bundle for a file-routed app. Writes the hashed assets + `manifest.json` to
|
|
24
|
+
* `outDir` and returns the manifest. Throws (with the bundler logs) on build failure — never
|
|
25
|
+
* silently ships a broken bundle.
|
|
26
|
+
*/
|
|
27
|
+
export async function buildClient(options) {
|
|
28
|
+
const { routesDir, outDir, clientModule } = options;
|
|
29
|
+
const resolve = options.resolve ?? ((file) => `${routesDir}/${file}`);
|
|
30
|
+
const publicPath = options.publicPath ?? "/assets/";
|
|
31
|
+
mkdirSync(outDir, { recursive: true });
|
|
32
|
+
const routeManifest = discoverRoutes(routesDir);
|
|
33
|
+
// The bootstrap's filename is `_velo`-namespaced (not `entry.ts`) so its `[name]` can't collide with
|
|
34
|
+
// a user route named `entry.tsx` when the CSS mapping below excludes the bootstrap's aggregate CSS.
|
|
35
|
+
const entryFile = `${outDir}/_nifra-entry.ts`;
|
|
36
|
+
writeFileSync(entryFile, generateClientEntry(routeManifest, { clientModule, resolve }));
|
|
37
|
+
// Every unique route/layout/`_404` file (sorted, stable), as ADDITIONAL entrypoints — Bun emits a
|
|
38
|
+
// named chunk per file that the bootstrap's lazy `import()` dedupes to (verified), so the manifest
|
|
39
|
+
// can map each route to its chunk URLs for matched-route preload. `resolve(file)` is the same
|
|
40
|
+
// specifier the bootstrap imports, so the entrypoint + lazy import are the same module (dedup).
|
|
41
|
+
const routeFiles = [
|
|
42
|
+
...new Set([
|
|
43
|
+
...routeManifest.routes.map((r) => r.file),
|
|
44
|
+
...Object.values(routeManifest.layouts).map((l) => l.file),
|
|
45
|
+
...(routeManifest.notFound ? [routeManifest.notFound.file] : []),
|
|
46
|
+
]),
|
|
47
|
+
].sort();
|
|
48
|
+
// `metafile: true` asks Bun for the input/output graph — specifically `outputs[js].entryPoint`
|
|
49
|
+
// (the source file) + `outputs[js].cssBundle` (that entry's emitted stylesheet). It's the robust
|
|
50
|
+
// entry→CSS link for per-route splitting: keyed by the unique source path, so it survives
|
|
51
|
+
// same-basename collisions (`index.tsx` + `blog/index.tsx`) that a filename match can't. Not yet in
|
|
52
|
+
// `@types/bun`'s `BuildConfig`, so spread it in (spread props skip the excess-property check).
|
|
53
|
+
const buildExtras = { metafile: true };
|
|
54
|
+
const result = await Bun.build({
|
|
55
|
+
entrypoints: [entryFile, ...routeFiles.map(resolve)],
|
|
56
|
+
outdir: outDir,
|
|
57
|
+
target: "browser",
|
|
58
|
+
naming: "[name]-[hash].[ext]",
|
|
59
|
+
publicPath,
|
|
60
|
+
splitting: true, // one chunk per lazily-imported route; shared deps deduped into shared chunks
|
|
61
|
+
// `import "./x.css"` in a route/component → bundled, minified, content-hashed `.css` asset (Bun
|
|
62
|
+
// strips the import from the JS; CSS bundling is on by default since Bun 1.2). Mapped to routes
|
|
63
|
+
// below — both the aggregate and per-route — via the metafile, for `<link>` injection.
|
|
64
|
+
...buildExtras,
|
|
65
|
+
minify: options.minify ?? true,
|
|
66
|
+
plugins: [...(options.plugins ?? [])],
|
|
67
|
+
...(options.conditions ? { conditions: [...options.conditions] } : {}),
|
|
68
|
+
...(options.define ? { define: { ...options.define } } : {}),
|
|
69
|
+
});
|
|
70
|
+
if (!result.success) {
|
|
71
|
+
throw new Error(`[nifra/web] client build failed:\n${result.logs.map((l) => String(l)).join("\n")}`);
|
|
72
|
+
}
|
|
73
|
+
const toUrl = (path) => `${publicPath}${basename(path)}`;
|
|
74
|
+
// Entry-point outputs come back in entrypoint order: [bootstrap, ...routeFiles]. Map each route file
|
|
75
|
+
// to its chunk URL by that order (guarded against drift), then a route's chunks = its layout chain +
|
|
76
|
+
// own file.
|
|
77
|
+
const entryPoints = result.outputs.filter((o) => o.kind === "entry-point");
|
|
78
|
+
const bootstrap = entryPoints[0];
|
|
79
|
+
if (bootstrap === undefined)
|
|
80
|
+
throw new Error("[nifra/web] build produced no entry-point output");
|
|
81
|
+
if (entryPoints.length !== routeFiles.length + 1) {
|
|
82
|
+
throw new Error(`[nifra/web] expected ${routeFiles.length + 1} entry-point outputs (bootstrap + ${routeFiles.length} routes), got ${entryPoints.length}`);
|
|
83
|
+
}
|
|
84
|
+
const fileToChunk = new Map();
|
|
85
|
+
routeFiles.forEach((file, i) => {
|
|
86
|
+
const out = entryPoints[i + 1]; // in range — length checked above
|
|
87
|
+
if (out !== undefined)
|
|
88
|
+
fileToChunk.set(file, toUrl(out.path));
|
|
89
|
+
});
|
|
90
|
+
const chunksFor = (chainFiles) => chainFiles.map((f) => fileToChunk.get(f)).filter((u) => u !== undefined);
|
|
91
|
+
const routes = {};
|
|
92
|
+
for (const route of routeManifest.routes) {
|
|
93
|
+
routes[route.id] = chunksFor([
|
|
94
|
+
...route.layoutIds.map((id) => routeManifest.layouts[id]?.file ?? ""),
|
|
95
|
+
route.file,
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
if (routeManifest.notFound)
|
|
99
|
+
routes._404 = chunksFor([routeManifest.notFound.file]);
|
|
100
|
+
// CSS — aggregate: an `import "./x.css"` anywhere → a content-hashed `.css` asset (Bun strips the
|
|
101
|
+
// import from the JS). The bootstrap lazily imports every route, so its **aggregate** stylesheet is
|
|
102
|
+
// the whole app's CSS — the always-safe fallback `createWebApp` links when a route has no per-route
|
|
103
|
+
// entry below. Fallback to all CSS assets if Bun emitted no distinct aggregate.
|
|
104
|
+
const bootstrapName = entryName(entryFile); // `_nifra-entry`
|
|
105
|
+
const cssNameOf = (path) => {
|
|
106
|
+
const base = basename(path);
|
|
107
|
+
return base.slice(0, base.lastIndexOf("-")); // strip `-${hash}.css`
|
|
108
|
+
};
|
|
109
|
+
const cssAssets = result.outputs.filter((o) => o.kind === "asset" && o.path.endsWith(".css"));
|
|
110
|
+
const aggregate = cssAssets
|
|
111
|
+
.filter((o) => cssNameOf(o.path) === bootstrapName)
|
|
112
|
+
.map((o) => toUrl(o.path));
|
|
113
|
+
const css = aggregate.length > 0 ? aggregate : cssAssets.map((o) => toUrl(o.path));
|
|
114
|
+
// CSS — per-route: each route/layout file is its own entrypoint, so the build metafile records its
|
|
115
|
+
// `cssBundle` — exactly the CSS that file's subtree uses (shared-component CSS is inlined into each
|
|
116
|
+
// consumer; verified). Keyed by the metafile's unique source `entryPoint`, so it survives
|
|
117
|
+
// same-basename collisions (`index.tsx` + `blog/index.tsx`) that a filename match can't. A page then
|
|
118
|
+
// links only its layout chain + own CSS (deduped); an empty array means the page needs no CSS at all.
|
|
119
|
+
// Absent (→ aggregate fallback) only if Bun emits no metafile/cssBundle — never silently incomplete.
|
|
120
|
+
const meta = result.metafile;
|
|
121
|
+
const cwd = process.cwd();
|
|
122
|
+
const cssByEntry = new Map();
|
|
123
|
+
for (const out of Object.values(meta?.outputs ?? {})) {
|
|
124
|
+
if (out.entryPoint !== undefined && out.cssBundle !== undefined) {
|
|
125
|
+
cssByEntry.set(resolvePath(cwd, out.entryPoint), toUrl(out.cssBundle));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const stylesFor = (chainFiles) => {
|
|
129
|
+
const urls = chainFiles
|
|
130
|
+
.map((f) => (f ? cssByEntry.get(resolvePath(resolve(f))) : undefined))
|
|
131
|
+
.filter((u) => u !== undefined);
|
|
132
|
+
return [...new Set(urls)];
|
|
133
|
+
};
|
|
134
|
+
const routeStyles = {};
|
|
135
|
+
if (css.length > 0 && cssByEntry.size > 0) {
|
|
136
|
+
for (const route of routeManifest.routes) {
|
|
137
|
+
routeStyles[route.id] = stylesFor([
|
|
138
|
+
...route.layoutIds.map((id) => routeManifest.layouts[id]?.file ?? ""),
|
|
139
|
+
route.file,
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
if (routeManifest.notFound)
|
|
143
|
+
routeStyles._404 = stylesFor([routeManifest.notFound.file]);
|
|
144
|
+
}
|
|
145
|
+
const manifest = {
|
|
146
|
+
entry: toUrl(bootstrap.path),
|
|
147
|
+
assets: result.outputs.map((o) => toUrl(o.path)),
|
|
148
|
+
routes,
|
|
149
|
+
...(css.length > 0 ? { css } : {}),
|
|
150
|
+
...(Object.keys(routeStyles).length > 0 ? { routeStyles } : {}),
|
|
151
|
+
};
|
|
152
|
+
writeFileSync(`${outDir}/manifest.json`, JSON.stringify(manifest, null, 2));
|
|
153
|
+
return manifest;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* react-dom's `exports["./server"]` maps the `bun` condition to a Bun-API server build that crashes
|
|
157
|
+
* on workerd, and `Bun.build` always applies the `bun` condition (it wins over `workerd`/`edge-light`),
|
|
158
|
+
* so conditions alone can't select the edge build. This shim pins `react-dom/server` to its edge build
|
|
159
|
+
* (`server.edge.js`, which exports `renderToReadableStream`). A no-op when nothing imports react-dom
|
|
160
|
+
* (e.g. a Solid worker) — the resolver only runs on a match.
|
|
161
|
+
*/
|
|
162
|
+
const reactDomEdgePlugin = (from) => ({
|
|
163
|
+
name: "nifra-react-dom-edge",
|
|
164
|
+
setup(build) {
|
|
165
|
+
build.onResolve({ filter: /^react-dom\/server$/ }, () => ({
|
|
166
|
+
path: Bun.resolveSync("react-dom/server.edge", from),
|
|
167
|
+
}));
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
/**
|
|
171
|
+
* `solid-js/web` selects its **server** runtime (`renderToStream`) via the `worker` condition, but
|
|
172
|
+
* `Bun.build` 1.3.14 **segfaults** when the `worker` condition is active (https://bun.report). And
|
|
173
|
+
* without `worker`, `browser` (which precedes the other server conditions in solid's exports map)
|
|
174
|
+
* wins → the *dom* runtime, which can't SSR. So this shim pins `solid-js/web` straight to its server
|
|
175
|
+
* build, sidestepping the crashing condition. Lazy (resolved on match) + a no-op when nothing imports
|
|
176
|
+
* `solid-js/web` (e.g. a React worker). Drop it (and use the `worker` condition) once Bun is fixed.
|
|
177
|
+
*/
|
|
178
|
+
const solidWebServerPlugin = (from) => ({
|
|
179
|
+
name: "nifra-solid-web-server",
|
|
180
|
+
setup(build) {
|
|
181
|
+
build.onResolve({ filter: /^solid-js\/web$/ }, () => {
|
|
182
|
+
// solid's `worker`/`node`/`deno` conditions all map to ./web/dist/server.js (its server build).
|
|
183
|
+
const pkg = Bun.resolveSync("solid-js/package.json", from);
|
|
184
|
+
return { path: pkg.replace(/package\.json$/, "web/dist/server.js") };
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
/**
|
|
189
|
+
* Build a self-contained **worker bundle** for a file-routed app on a disk-less edge (Cloudflare
|
|
190
|
+
* Workers / workerd). Discovers routes (build-time fs), codegens the static-import server manifest
|
|
191
|
+
* (`generateServerManifest`, written next to `serverEntry`), then bundles `serverEntry` with
|
|
192
|
+
* `Bun.build` using **edge conditions** + the adapter's SSR plugins. The output imports no `node:fs`
|
|
193
|
+
* and does no dynamic-path import, so it runs on workerd: point `wrangler.toml`'s `main` at it and
|
|
194
|
+
* serve the client assets via Workers Assets. Throws (with the bundler logs) on failure — never
|
|
195
|
+
* silently ships a broken worker.
|
|
196
|
+
*/
|
|
197
|
+
export async function buildServer(options) {
|
|
198
|
+
const { routesDir, serverEntry, outDir, clientEntry } = options;
|
|
199
|
+
const entryDir = dirname(serverEntry);
|
|
200
|
+
const manifestFile = options.manifestFile ?? "server-manifest.ts";
|
|
201
|
+
// Default: import routes relative from the generated manifest (next to serverEntry) to routesDir.
|
|
202
|
+
const rel = relative(entryDir, routesDir).replaceAll("\\", "/");
|
|
203
|
+
const resolve = options.resolve ?? ((file) => `./${rel}/${file}`);
|
|
204
|
+
mkdirSync(outDir, { recursive: true });
|
|
205
|
+
const lazy = options.lazy ?? false;
|
|
206
|
+
const target = options.target ?? "browser";
|
|
207
|
+
// Edge (browser) target: Bun's `bun` condition contaminates react-dom's server build + the `worker`
|
|
208
|
+
// condition segfaults Bun.build on solid, so force the edge/server builds via shims. The `node`/`bun`
|
|
209
|
+
// targets resolve those correctly via their own condition, so the shims (and edge conditions) don't
|
|
210
|
+
// apply — defaults become `[target]` (e.g. react-dom → server.node.js under `node`).
|
|
211
|
+
const edge = target === "browser";
|
|
212
|
+
const conditions = options.conditions ?? (edge ? ["workerd", "edge-light", "browser"] : [target]);
|
|
213
|
+
const manifest = discoverRoutes(routesDir);
|
|
214
|
+
writeFileSync(`${entryDir}/${manifestFile}`, generateServerManifest(manifest, { resolve, clientEntry, lazy }));
|
|
215
|
+
const result = await Bun.build({
|
|
216
|
+
entrypoints: [serverEntry],
|
|
217
|
+
outdir: outDir,
|
|
218
|
+
target,
|
|
219
|
+
conditions: [...conditions],
|
|
220
|
+
define: { ...(options.define ?? { "process.env.NODE_ENV": '"production"' }) },
|
|
221
|
+
minify: options.minify ?? true,
|
|
222
|
+
// Lazy → one chunk per route (loaded on first request); eager → a single self-contained file.
|
|
223
|
+
splitting: lazy,
|
|
224
|
+
plugins: [
|
|
225
|
+
...(edge ? [reactDomEdgePlugin(entryDir), solidWebServerPlugin(entryDir)] : []),
|
|
226
|
+
...(options.plugins ?? []),
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
if (!result.success) {
|
|
230
|
+
throw new Error(`[nifra/web] server build failed:\n${result.logs.map((l) => String(l)).join("\n")}`);
|
|
231
|
+
}
|
|
232
|
+
const entryOutput = result.outputs.find((o) => o.kind === "entry-point");
|
|
233
|
+
if (entryOutput === undefined) {
|
|
234
|
+
throw new Error("[nifra/web] server build produced no entry-point output");
|
|
235
|
+
}
|
|
236
|
+
return { worker: entryOutput.path, outputs: result.outputs.map((o) => o.path) };
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web/client` — the agnostic browser layer for client-side navigation. It wires the pure
|
|
3
|
+
* router store ({@link ClientRouter}) to the browser: `pushState` on navigate, `popstate` →
|
|
4
|
+
* navigate, and delegated interception of same-origin `<a>` clicks (client transition instead of
|
|
5
|
+
* a full page load). DOM-only — never imported on the server, so the store stays SSR-safe.
|
|
6
|
+
*/
|
|
7
|
+
import type { Meta } from "./manifest.js";
|
|
8
|
+
import type { ClientRouter } from "./router.js";
|
|
9
|
+
export interface InstallHistoryOptions {
|
|
10
|
+
/** Full-page fallback when a client navigation can't proceed (default: `location.assign`). */
|
|
11
|
+
readonly fallback?: (path: string) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Attach history + link interception to a router. Returns a teardown function that removes the
|
|
15
|
+
* listeners. A data-fetch failure during a client navigation falls back to a full-page load, so
|
|
16
|
+
* navigation degrades gracefully rather than leaving the user stuck.
|
|
17
|
+
*/
|
|
18
|
+
export declare function installHistory(router: ClientRouter, options?: InstallHistoryOptions): () => void;
|
|
19
|
+
/**
|
|
20
|
+
* Intercept submissions of same-origin `<form method="post">` whose action targets an app route:
|
|
21
|
+
* submit via the router (no full reload — POST the action, then revalidate the active loader). On
|
|
22
|
+
* failure it falls back to a native submit, so the form still works. Returns a teardown function.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Sync the document head to a route's resolved {@link Meta} on client navigation. Sets the title
|
|
26
|
+
* (when provided) and replaces the **managed** (`data-nifra`) `<meta>`/`<link>` tags — static head
|
|
27
|
+
* content (charset, hand-written tags) is never touched. SSR injects the same `data-nifra` tags, so
|
|
28
|
+
* the first navigation cleanly takes over from the server-rendered head.
|
|
29
|
+
*/
|
|
30
|
+
export declare function applyHead(head: Meta): void;
|
|
31
|
+
export declare function installForms(router: ClientRouter): () => void;
|
|
32
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,qBAAqB;IACpC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,qBAA0B,GAClC,MAAM,IAAI,CAsJZ;AAED;;;;GAIG;AACH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAW1C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,CAmB7D"}
|