defuss-ssg 0.5.1 → 0.6.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 +213 -260
- package/dist/cli.mjs +14 -9
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +2 -2
- package/dist/{serve-BJ00mBAJ.mjs → serve-Cd4Pw98E.mjs} +1 -1
- package/dist/{vite-DySvB3OP.cjs → vite-CBAZNNYA.cjs} +747 -153
- package/dist/{vite-B4oPT39d.mjs → vite-CaqPNORI.mjs} +747 -153
- package/dist/{vite-CMGAfJFW.d.cts → vite-DtwFnDf2.d.cts} +4 -4
- package/dist/{vite-CMGAfJFW.d.mts → vite-DtwFnDf2.d.mts} +4 -4
- package/dist/vite.cjs +1 -1
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,370 +1,323 @@
|
|
|
1
|
-
|
|
1
|
+
# defuss-ssg
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Static site generation, request-time dev SSR, file-based endpoints, and production serving for defuss.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<code>defuss-ssg</code>
|
|
5
|
+
`defuss-ssg` is both a CLI and a library:
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
- `dev` starts a Vite server and renders MD/MDX pages on demand through SSR.
|
|
8
|
+
- `build` renders static HTML, bundles client components, compiles endpoints, and copies assets.
|
|
9
|
+
- `serve` serves built output with `defuss-express`, plus dynamic endpoints and optional RPC.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Use Bun for package management. The published package targets Node `^20.19.0 || >=22.12.0`.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## What It Supports
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
- Markdown and MDX pages from `pages/` or `src/pages/`
|
|
16
|
+
- YAML or TOML frontmatter exposed as `meta`
|
|
17
|
+
- GitHub Flavored Markdown via `remark-gfm`
|
|
18
|
+
- KaTeX math via `$...$` and `$$...$$`
|
|
19
|
+
- defuss components imported into MDX and HTML-like pages
|
|
20
|
+
- Automatic hydration boundaries for components rendered from `components/`, `src/components/`, `csr/`, or `src/csr/`
|
|
21
|
+
- Static assets copied from `assets/` or `src/assets/`
|
|
22
|
+
- File-based API routes from `pages/**/*.ts` and `pages/**/*.js`
|
|
23
|
+
- Root `index.mdx`, `index.md`, or `index.html` fallback when no pages directory exists
|
|
24
|
+
- Pre-rendered endpoints via `prerender = true` and `getStaticPaths()`
|
|
25
|
+
- RPC auto-discovery from `rpc.ts` or `rpc.js` when `defuss-rpc` is installed
|
|
26
|
+
- Plugin hooks for `pre`, `page-vdom`, `page-dom`, `page-html`, and `post`
|
|
27
|
+
- Multicore production serving through `--multicore` or `workers: "auto"`
|
|
16
28
|
|
|
17
|
-
|
|
29
|
+
## Install
|
|
18
30
|
|
|
19
|
-
|
|
20
|
-
Usage
|
|
21
|
-
</h3>
|
|
22
|
-
|
|
23
|
-
Simply generate a static site from a content directory to an output directory with full defuss-MDX (GFM + Frontmatter) support:
|
|
31
|
+
Run directly:
|
|
24
32
|
|
|
25
33
|
```bash
|
|
26
|
-
bunx defuss-ssg build ./
|
|
34
|
+
bunx defuss-ssg build ./my-site
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
Or
|
|
37
|
+
Or add it as a dev dependency:
|
|
30
38
|
|
|
31
|
-
```bash
|
|
32
|
-
bun add -
|
|
39
|
+
```bash
|
|
40
|
+
bun add -D defuss-ssg
|
|
33
41
|
```
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
## Quick Start
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
```text
|
|
46
|
+
my-site/
|
|
47
|
+
├-- pages/
|
|
48
|
+
| ├-- index.mdx
|
|
49
|
+
| └-- api/
|
|
50
|
+
| └-- ping.json.ts
|
|
51
|
+
├-- components/
|
|
52
|
+
| └-- button.tsx
|
|
53
|
+
├-- assets/
|
|
54
|
+
| └-- styles.css
|
|
55
|
+
├-- config.ts
|
|
56
|
+
└-- rpc.ts
|
|
41
57
|
```
|
|
42
58
|
|
|
43
|
-
|
|
59
|
+
Minimal config:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { rehypePlugins, remarkPlugins, type SsgConfig } from "defuss-ssg";
|
|
63
|
+
|
|
64
|
+
const config: SsgConfig = {
|
|
65
|
+
pages: "pages",
|
|
66
|
+
output: "dist",
|
|
67
|
+
components: "components",
|
|
68
|
+
assets: "assets",
|
|
69
|
+
tmp: ".ssg-temp",
|
|
70
|
+
plugins: [],
|
|
71
|
+
remarkPlugins: [...remarkPlugins],
|
|
72
|
+
rehypePlugins: [...rehypePlugins],
|
|
73
|
+
rpc: true,
|
|
74
|
+
};
|
|
44
75
|
|
|
45
|
-
|
|
46
|
-
defuss-ssg dev ./folder
|
|
76
|
+
export default config;
|
|
47
77
|
```
|
|
48
78
|
|
|
49
|
-
|
|
79
|
+
Example page:
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
```mdx
|
|
82
|
+
---
|
|
83
|
+
title: Home
|
|
84
|
+
---
|
|
54
85
|
|
|
55
|
-
|
|
86
|
+
import { Button } from "../components/button.js";
|
|
56
87
|
|
|
57
|
-
|
|
88
|
+
# {meta.title}
|
|
58
89
|
|
|
59
|
-
|
|
90
|
+
This page uses MDX, frontmatter, and a defuss component.
|
|
60
91
|
|
|
61
|
-
|
|
62
|
-
defuss-ssg serve ./folder
|
|
92
|
+
<Button label="Click me" />
|
|
63
93
|
```
|
|
64
94
|
|
|
65
|
-
|
|
95
|
+
Example component:
|
|
66
96
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
```tsx
|
|
98
|
+
export function Button({ label }: { label: string }) {
|
|
99
|
+
return <button type="button">{label}</button>;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
70
102
|
|
|
71
|
-
|
|
103
|
+
Build the site:
|
|
72
104
|
|
|
73
105
|
```bash
|
|
74
|
-
|
|
106
|
+
defuss-ssg build ./my-site
|
|
107
|
+
```
|
|
75
108
|
|
|
76
|
-
|
|
109
|
+
Start Vite-powered development:
|
|
77
110
|
|
|
78
|
-
|
|
111
|
+
```bash
|
|
112
|
+
defuss-ssg dev ./my-site
|
|
113
|
+
```
|
|
79
114
|
|
|
80
|
-
|
|
81
|
-
bun run cli-dev ./example
|
|
115
|
+
Serve the already built output:
|
|
82
116
|
|
|
83
|
-
|
|
84
|
-
|
|
117
|
+
```bash
|
|
118
|
+
defuss-ssg serve ./my-site
|
|
85
119
|
```
|
|
86
120
|
|
|
87
|
-
|
|
121
|
+
`serve` expects existing build output in `dist/`, so run `build` first.
|
|
88
122
|
|
|
89
|
-
|
|
123
|
+
## How It Works
|
|
90
124
|
|
|
91
|
-
|
|
125
|
+
### Dev Mode
|
|
92
126
|
|
|
93
|
-
|
|
94
|
-
import { setup, build, dev, serve } from "defuss-ssg";
|
|
127
|
+
`defuss-ssg dev` starts a Vite server rooted at your project. Requests for MD and MDX pages are resolved through Vite's transform pipeline and rendered on demand with SSR. Page, component, endpoint, RPC, config, and asset changes are coalesced before reload. CSS assets are hot-swapped when possible, and hydration boundaries restore local form and scroll state across component updates.
|
|
95
128
|
|
|
96
|
-
|
|
129
|
+
By default, the CLI keeps `dist/` refreshed during dev as a compatibility fallback for middleware paths. Programmatic users can disable that bridge with `writeDevOutput: false`.
|
|
97
130
|
|
|
98
|
-
|
|
99
|
-
const setupStatus = await setup("./my-site");
|
|
100
|
-
if (setupStatus.code !== "OK") {
|
|
101
|
-
console.error("Setup failed:", setupStatus.message);
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
131
|
+
### Build Mode
|
|
104
132
|
|
|
105
|
-
|
|
106
|
-
await build({
|
|
107
|
-
projectDir: "./my-site",
|
|
108
|
-
debug: true,
|
|
109
|
-
});
|
|
133
|
+
`defuss-ssg build` loads `config.ts`, copies the project into `.ssg-temp`, renders each page through a temporary Vite SSR server, applies automatic hydration wrapping, bundles client components, compiles endpoints into `.endpoints`, copies assets into `dist`, and removes the temp directory unless debug mode is enabled.
|
|
110
134
|
|
|
111
|
-
|
|
112
|
-
await dev({
|
|
113
|
-
projectDir: "./my-site",
|
|
114
|
-
debug: true,
|
|
115
|
-
});
|
|
135
|
+
### Serve Mode
|
|
116
136
|
|
|
117
|
-
|
|
118
|
-
await serve({
|
|
119
|
-
projectDir: "./my-site",
|
|
120
|
-
workers: "auto",
|
|
121
|
-
});
|
|
122
|
-
})();
|
|
123
|
-
```
|
|
137
|
+
`defuss-ssg serve` reads the built output from `dist/` and serves it with `defuss-express`. Dynamic endpoint modules are registered at runtime, and `rpc.ts` or `rpc.js` is compiled and initialized automatically when RPC is enabled and `defuss-rpc` is installed.
|
|
124
138
|
|
|
125
|
-
|
|
126
|
-
Overview
|
|
127
|
-
</h3>
|
|
139
|
+
## Endpoints
|
|
128
140
|
|
|
129
|
-
|
|
141
|
+
Endpoint source files live under `pages/` and export HTTP method handlers.
|
|
130
142
|
|
|
131
|
-
|
|
143
|
+
```ts
|
|
144
|
+
import type { APIRoute } from "defuss-ssg";
|
|
132
145
|
|
|
133
|
-
|
|
146
|
+
export const GET: APIRoute = async () => {
|
|
147
|
+
return Response.json({ ok: true, ts: Date.now() });
|
|
148
|
+
};
|
|
149
|
+
```
|
|
134
150
|
|
|
135
|
-
|
|
151
|
+
Supported method exports are `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, and `ALL`.
|
|
136
152
|
|
|
137
|
-
|
|
153
|
+
Dynamic routes use bracket syntax:
|
|
138
154
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- **Dev Mode**: Vite-backed development server with auto-rebuild and full reload
|
|
144
|
-
- **Production Runtime**: `defuss-express` serves static output plus dynamic endpoints and RPC
|
|
145
|
-
- **TypeScript Ready**: Full TypeScript support for components and configuration
|
|
146
|
-
- **Asset Handling**: Automatic copying of static assets to output directory
|
|
147
|
-
- **Flexible Configuration**: Configurable via TypeScript config file with sensible defaults
|
|
155
|
+
```text
|
|
156
|
+
pages/api/[id].json.ts -> /api/:id.json
|
|
157
|
+
pages/feed.xml.ts -> /feed.xml
|
|
158
|
+
```
|
|
148
159
|
|
|
149
|
-
|
|
160
|
+
To pre-render an endpoint during `build`, export `prerender = true`. Dynamic routes can also export `getStaticPaths()`.
|
|
150
161
|
|
|
151
|
-
|
|
162
|
+
```ts
|
|
163
|
+
import type { APIRoute } from "defuss-ssg";
|
|
152
164
|
|
|
153
|
-
|
|
165
|
+
export const prerender = true;
|
|
154
166
|
|
|
155
|
-
|
|
167
|
+
export const getStaticPaths = () => [
|
|
168
|
+
{ params: { slug: "hello-world" } },
|
|
169
|
+
{ params: { slug: "release-notes" } },
|
|
170
|
+
];
|
|
156
171
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
│ ├-- index.mdx
|
|
161
|
-
│ └-- blog/
|
|
162
|
-
│ └-- hello-world.mdx
|
|
163
|
-
├-- components/
|
|
164
|
-
│ └-- button.tsx
|
|
165
|
-
├-- assets/
|
|
166
|
-
│ └-- styles.css
|
|
167
|
-
└-- config.ts
|
|
172
|
+
export const GET: APIRoute = async ({ params }) => {
|
|
173
|
+
return new Response(`Post: ${params.slug}`);
|
|
174
|
+
};
|
|
168
175
|
```
|
|
169
|
-
Then run `defuss-ssg build ./my-site` and a `dist` folder will be created with the complete static build.
|
|
170
176
|
|
|
171
|
-
|
|
177
|
+
## RPC
|
|
172
178
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
</h3>
|
|
176
|
-
|
|
177
|
-
You can customize the paths and behaviour of the build process, by creating a simple `config.ts` file in the project folder.
|
|
178
|
-
|
|
179
|
-
##### Example `config.ts` file
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
import { remarkPlugins, rehypePlugins } from "defuss-ssg";
|
|
179
|
+
RPC is optional and discovered automatically from `rpc.ts` or `rpc.js` in the project root. Install `defuss-rpc` to enable it.
|
|
183
180
|
|
|
181
|
+
```ts
|
|
184
182
|
export default {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
plugins: [],
|
|
183
|
+
mathApi: {
|
|
184
|
+
add: async (a: number, b: number) => a + b,
|
|
185
|
+
},
|
|
186
|
+
greetApi: {
|
|
187
|
+
hello: async (name: string) => `Hello, ${name}!`,
|
|
188
|
+
},
|
|
192
189
|
};
|
|
193
190
|
```
|
|
194
191
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
`defuss-ssg` plugins can be registered via the `plugins` array and are executed in order of registration, in each build phase.
|
|
198
|
-
|
|
199
|
-
##### Example MDX page (`pages/index.mdx`)
|
|
200
|
-
|
|
201
|
-
```mdx
|
|
202
|
-
---
|
|
203
|
-
title: Home Page
|
|
204
|
-
---
|
|
192
|
+
When RPC is active, `defuss-ssg` exposes:
|
|
205
193
|
|
|
206
|
-
|
|
194
|
+
- `POST /rpc`
|
|
195
|
+
- `POST /rpc/schema`
|
|
207
196
|
|
|
208
|
-
|
|
197
|
+
Set `rpc: false` in `config.ts` to disable RPC discovery.
|
|
209
198
|
|
|
210
|
-
|
|
199
|
+
## Plugins
|
|
211
200
|
|
|
212
|
-
|
|
213
|
-
```
|
|
201
|
+
`defuss-ssg` plugins run in build order and can modify the pipeline at distinct phases.
|
|
214
202
|
|
|
215
|
-
|
|
203
|
+
```ts
|
|
204
|
+
import type { SsgPlugin } from "defuss-ssg";
|
|
216
205
|
|
|
217
|
-
|
|
206
|
+
const htmlStampPlugin: SsgPlugin = {
|
|
207
|
+
name: "html-stamp",
|
|
208
|
+
phase: "page-html",
|
|
209
|
+
mode: "both",
|
|
210
|
+
fn: (html, relativeOutputHtmlFilePath) => {
|
|
211
|
+
return html.replace(
|
|
212
|
+
"</body>",
|
|
213
|
+
`<!-- built:${relativeOutputHtmlFilePath} --></body>`,
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
218
217
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return (
|
|
222
|
-
<button type="button" onClick={() => alert("Button clicked!")}>
|
|
223
|
-
{label}
|
|
224
|
-
</button>
|
|
225
|
-
);
|
|
218
|
+
export default {
|
|
219
|
+
plugins: [htmlStampPlugin],
|
|
226
220
|
};
|
|
227
221
|
```
|
|
228
222
|
|
|
223
|
+
Available phases:
|
|
229
224
|
|
|
230
|
-
|
|
225
|
+
- `pre`: before a full build starts
|
|
226
|
+
- `page-vdom`: after page VDOM creation and before render
|
|
227
|
+
- `page-dom`: after DOM render and before serialization
|
|
228
|
+
- `page-html`: after HTML serialization and before write
|
|
229
|
+
- `post`: after the build completes
|
|
231
230
|
|
|
232
|
-
|
|
231
|
+
`page-vdom` hooks receive the page props/module exports as their fifth argument.
|
|
233
232
|
|
|
234
|
-
|
|
233
|
+
## Programmatic API
|
|
235
234
|
|
|
236
|
-
|
|
235
|
+
```ts
|
|
236
|
+
import { build, dev, serve, setup } from "defuss-ssg";
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
import { rule, transval, access } from 'defuss-transval';
|
|
238
|
+
const projectDir = "./my-site";
|
|
240
239
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
email: string;
|
|
246
|
-
settings: {
|
|
247
|
-
theme: 'light' | 'dark';
|
|
248
|
-
notifications: boolean;
|
|
249
|
-
};
|
|
250
|
-
};
|
|
251
|
-
posts: Array<{
|
|
252
|
-
title: string;
|
|
253
|
-
published: boolean;
|
|
254
|
-
import { SsgPlugin } from "defuss-ssg";
|
|
240
|
+
const setupStatus = await setup(projectDir);
|
|
241
|
+
if (setupStatus.code !== "OK") {
|
|
242
|
+
throw new Error(setupStatus.message);
|
|
243
|
+
}
|
|
255
244
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return html.replace("old-text", "new-text");
|
|
262
|
-
},
|
|
263
|
-
};
|
|
245
|
+
await build({
|
|
246
|
+
projectDir,
|
|
247
|
+
mode: "build",
|
|
248
|
+
debug: true,
|
|
249
|
+
});
|
|
264
250
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
251
|
+
await dev({
|
|
252
|
+
projectDir,
|
|
253
|
+
port: 3000,
|
|
254
|
+
host: true,
|
|
255
|
+
writeDevOutput: true,
|
|
256
|
+
});
|
|
270
257
|
|
|
271
|
-
|
|
258
|
+
await serve({
|
|
259
|
+
projectDir,
|
|
260
|
+
port: 3000,
|
|
261
|
+
workers: "auto",
|
|
262
|
+
});
|
|
263
|
+
```
|
|
272
264
|
|
|
273
|
-
|
|
274
|
-
- **page-vdom**: After VDOM creation for each page
|
|
275
|
-
- **page-dom**: After DOM rendering for each page
|
|
276
|
-
- **page-html**: After HTML serialization for each page
|
|
277
|
-
- **post**: After build completes
|
|
265
|
+
The main package exports `build`, `dev`, `serve`, `setup`, config defaults, endpoint types, RPC helpers, and plugin types.
|
|
278
266
|
|
|
267
|
+
Advanced subpath exports:
|
|
279
268
|
|
|
280
|
-
|
|
269
|
+
- `defuss-ssg/vite`: exposes `defussSsg()` for custom Vite integration
|
|
270
|
+
- `defuss-ssg/runtime`: exposes the client runtime used for navigation, hydration, and live reload
|
|
281
271
|
|
|
282
|
-
|
|
272
|
+
Most projects only need the main package export.
|
|
283
273
|
|
|
284
|
-
|
|
274
|
+
## CLI Reference
|
|
285
275
|
|
|
286
|
-
|
|
276
|
+
```bash
|
|
277
|
+
defuss-ssg [dev|build|serve] [folder] [--debug] [--multicore]
|
|
287
278
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
---
|
|
279
|
+
No args -> dev .
|
|
280
|
+
Single path -> dev <path>
|
|
281
|
+
Single command -> <command> .
|
|
282
|
+
Command + folder -> <command> <folder>
|
|
293
283
|
```
|
|
294
284
|
|
|
295
|
-
|
|
296
|
-
- **Math Support**: KaTeX rendering with `$...$` and `$$...$$`
|
|
297
|
-
- **Custom Plugins**: Extend MDX processing with remark/rehype plugins
|
|
298
|
-
|
|
299
|
-
<h3 align="center">
|
|
285
|
+
When `pages`, `components`, or `assets` are not configured explicitly, `defuss-ssg` prefers `src/pages`, `src/components`, `src/csr`, and `src/assets` before falling back to their project-root equivalents. If no pages directory exists, it falls back to root `index.mdx`, then `index.md`, then `index.html`.
|
|
300
286
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
</h3>
|
|
287
|
+
Commands:
|
|
304
288
|
|
|
305
|
-
|
|
289
|
+
- `dev`: starts the Vite dev server on port `3000` by default
|
|
290
|
+
- `build`: generates the static site into `dist/`
|
|
291
|
+
- `serve`: serves the built output from `dist/`
|
|
306
292
|
|
|
307
|
-
|
|
308
|
-
2. **Compile MDX**: Process MDX files to ESM JavaScript
|
|
309
|
-
3. **Compile Components**: Bundle components with esbuild
|
|
310
|
-
4. **Evaluate Pages**: Run page functions to generate VDOM
|
|
311
|
-
5. **Render HTML**: Convert VDOM to HTML using defuss/server
|
|
312
|
-
6. **Run Plugins**: Execute plugins at various phases
|
|
313
|
-
7. **Copy Assets**: Copy static assets to output
|
|
314
|
-
8. **Clean Up**: Remove temporary files (unless debug mode)
|
|
293
|
+
Flags:
|
|
315
294
|
|
|
316
|
-
|
|
295
|
+
- `--debug` or `-d`: enable verbose logging
|
|
296
|
+
- `--multicore`: use `workers: "auto"` for `serve`
|
|
317
297
|
|
|
318
|
-
|
|
298
|
+
## Local Package Development
|
|
319
299
|
|
|
320
|
-
|
|
300
|
+
To work on `defuss-ssg` inside this monorepo:
|
|
321
301
|
|
|
322
302
|
```bash
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
303
|
+
git clone https://github.com/kyr0/defuss.git
|
|
304
|
+
cd defuss/packages/ssg
|
|
305
|
+
bun install
|
|
306
|
+
bun run build
|
|
307
|
+
bun run cli-dev
|
|
328
308
|
```
|
|
329
309
|
|
|
330
|
-
|
|
331
|
-
Benchmark
|
|
332
|
-
</h3>
|
|
310
|
+
The example project used by the package scripts lives in `../../example-ssg/`.
|
|
333
311
|
|
|
334
|
-
|
|
312
|
+
## Benchmarking
|
|
313
|
+
|
|
314
|
+
The benchmark scripts are for local experiments, not committed performance guarantees.
|
|
335
315
|
|
|
336
316
|
```bash
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
1024 connections with 256 pipelining factor
|
|
340
|
-
8 workers
|
|
341
|
-
|
|
342
|
-
/
|
|
343
|
-
┌─────────┬────────┬─────────┬─────────┬─────────┬────────────┬────────────┬─────────┐
|
|
344
|
-
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
|
|
345
|
-
├─────────┼────────┼─────────┼─────────┼─────────┼────────────┼────────────┼─────────┤
|
|
346
|
-
│ Latency │ 617 ms │ 4708 ms │ 5629 ms │ 6230 ms │ 4367.37 ms │ 1263.71 ms │ 7115 ms │
|
|
347
|
-
└─────────┴────────┴─────────┴─────────┴─────────┴────────────┴────────────┴─────────┘
|
|
348
|
-
┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬─────────┬─────────┐
|
|
349
|
-
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
|
|
350
|
-
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤
|
|
351
|
-
│ Req/Sec │ 41,215 │ 41,215 │ 54,559 │ 66,751 │ 55,371.2 │ 5,492.3 │ 41,210 │
|
|
352
|
-
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤
|
|
353
|
-
│ Bytes/Sec │ 8.37 MB │ 8.37 MB │ 11.1 MB │ 13.5 MB │ 11.2 MB │ 1.11 MB │ 8.37 MB │
|
|
354
|
-
└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴─────────┴─────────┘
|
|
355
|
-
|
|
356
|
-
Req/Bytes counts sampled once per second.
|
|
357
|
-
# of samples: 240
|
|
358
|
-
|
|
359
|
-
1923k requests in 30.08s, 337 MB read
|
|
317
|
+
bun run bench
|
|
318
|
+
bun run bench:rpc
|
|
360
319
|
```
|
|
361
320
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
<img src="https://raw.githubusercontent.com/kyr0/defuss/refs/heads/main/assets/defuss_comic.png" width="400px" />
|
|
365
|
-
|
|
366
|
-
</p>
|
|
321
|
+
Benchmark result snapshots are written to `.tmp/bench-results.json` by default. Override that path with `RESULTS_FILE=/path/to/file.json` if needed.
|
|
367
322
|
|
|
368
|
-
|
|
369
|
-
<i><b>Come visit us on <code>defuss</code> Island!</b></i>
|
|
370
|
-
</p>
|
|
323
|
+
For local load-balancing experiments, use `scripts/lb.ts` directly.
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { v as validateProjectDir, b as build } from './vite-
|
|
3
|
-
import { d as dev, s as serve } from './serve-
|
|
2
|
+
import { v as validateProjectDir, b as build } from './vite-CaqPNORI.mjs';
|
|
3
|
+
import { d as dev, s as serve } from './serve-Cd4Pw98E.mjs';
|
|
4
4
|
import { join, dirname, resolve } from 'node:path';
|
|
5
5
|
import { existsSync, readFileSync } from 'node:fs';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
@@ -173,27 +173,32 @@ Continuing anyway - dependencies may already be available.`
|
|
|
173
173
|
const debug = args.includes("--debug") || args.includes("-d");
|
|
174
174
|
const multicore = args.includes("--multicore");
|
|
175
175
|
const positional = args.filter((a) => !a.startsWith("-"));
|
|
176
|
-
const
|
|
176
|
+
const commands = /* @__PURE__ */ new Set(["dev", "build", "serve"]);
|
|
177
|
+
const usage = "Usage: defuss-ssg [dev|build|serve] [folder]\n No args => dev .\n Single path => dev <path>\n Single command => <command> .\n Command + folder => <command> <folder>\n Flags: [--debug] [--multicore]";
|
|
177
178
|
let command;
|
|
178
179
|
let folder;
|
|
179
180
|
if (positional.length === 0) {
|
|
180
|
-
command = "
|
|
181
|
+
command = "dev";
|
|
181
182
|
folder = ".";
|
|
182
183
|
} else if (positional.length === 1) {
|
|
183
184
|
const arg = positional[0];
|
|
184
|
-
if (arg
|
|
185
|
+
if (commands.has(arg)) {
|
|
185
186
|
command = arg;
|
|
186
187
|
folder = ".";
|
|
187
|
-
} else if (arg.startsWith(".") || arg.startsWith("/")) {
|
|
188
|
-
command = "serve";
|
|
189
|
-
folder = arg;
|
|
190
188
|
} else {
|
|
189
|
+
command = "dev";
|
|
190
|
+
folder = arg;
|
|
191
|
+
}
|
|
192
|
+
} else if (positional.length === 2) {
|
|
193
|
+
if (!commands.has(positional[0])) {
|
|
191
194
|
console.error(usage);
|
|
192
195
|
process.exit(1);
|
|
193
196
|
}
|
|
194
|
-
} else {
|
|
195
197
|
command = positional[0];
|
|
196
198
|
folder = positional[1];
|
|
199
|
+
} else {
|
|
200
|
+
console.error(usage);
|
|
201
|
+
process.exit(1);
|
|
197
202
|
}
|
|
198
203
|
const projectDir = resolve(folder);
|
|
199
204
|
await setup(projectDir);
|