hadars 1.0.5 → 1.0.7
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 +14 -14
- package/dist/{chunk-EJUCAJXR.js → chunk-VAR5KTG3.js} +12 -1
- package/dist/cli.js +38 -13
- package/dist/cloudflare.cjs +12 -1
- package/dist/cloudflare.js +1 -1
- package/dist/lambda.cjs +12 -1
- package/dist/lambda.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,30 +21,30 @@ Bring your own router (or none), keep your components as plain React, and get SS
|
|
|
21
21
|
## Benchmarks
|
|
22
22
|
|
|
23
23
|
<!-- BENCHMARK_START -->
|
|
24
|
-
> Last run: 2026-
|
|
25
|
-
> hadars is **
|
|
24
|
+
> Last run: 2026-05-12 · 120s · 100 connections · Bun runtime
|
|
25
|
+
> hadars is **8.9x faster** in requests/sec
|
|
26
26
|
|
|
27
27
|
**Throughput** (autocannon, 120s)
|
|
28
28
|
|
|
29
29
|
| Metric | hadars | Next.js |
|
|
30
30
|
|---|---:|---:|
|
|
31
|
-
| Requests/sec | **
|
|
32
|
-
| Latency median | **
|
|
33
|
-
| Latency p99 | **
|
|
34
|
-
| Throughput | **
|
|
35
|
-
| Peak RSS |
|
|
36
|
-
| Avg RSS |
|
|
37
|
-
| Build time | 0.
|
|
31
|
+
| Requests/sec | **152** | 17 |
|
|
32
|
+
| Latency median | **603 ms** | 2762 ms |
|
|
33
|
+
| Latency p99 | **1307 ms** | 4162 ms |
|
|
34
|
+
| Throughput | **43.4** MB/s | 9.4 MB/s |
|
|
35
|
+
| Peak RSS | 788.6 MB | **477.3 MB** |
|
|
36
|
+
| Avg RSS | 617.5 MB | **425.6 MB** |
|
|
37
|
+
| Build time | 0.6 s | 6.1 s |
|
|
38
38
|
|
|
39
39
|
**Page load** (Playwright · Chromium headless · median)
|
|
40
40
|
|
|
41
41
|
| Metric | hadars | Next.js |
|
|
42
42
|
|---|---:|---:|
|
|
43
|
-
| TTFB | **
|
|
44
|
-
| FCP | **
|
|
45
|
-
| DOMContentLoaded | **
|
|
46
|
-
| Load | **
|
|
47
|
-
| Peak RSS |
|
|
43
|
+
| TTFB | **18 ms** | 43 ms |
|
|
44
|
+
| FCP | **96 ms** | 144 ms |
|
|
45
|
+
| DOMContentLoaded | **39 ms** | 131 ms |
|
|
46
|
+
| Load | **121 ms** | 177 ms |
|
|
47
|
+
| Peak RSS | 457.3 MB | **288.8 MB** |
|
|
48
48
|
<!-- BENCHMARK_END -->
|
|
49
49
|
|
|
50
50
|
## Quick start
|
|
@@ -180,7 +180,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
180
180
|
globalThis.__hadarsContext = context;
|
|
181
181
|
const element = createElement(App, props);
|
|
182
182
|
let bodyHtml = null;
|
|
183
|
-
if (opts.
|
|
183
|
+
if (opts.dataOnly) {
|
|
184
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
185
|
+
globalThis.__hadarsContext = context;
|
|
186
|
+
try {
|
|
187
|
+
await renderPreflight(element);
|
|
188
|
+
} finally {
|
|
189
|
+
globalThis.__hadarsUnsuspend = null;
|
|
190
|
+
globalThis.__hadarsContext = null;
|
|
191
|
+
}
|
|
192
|
+
} else if (opts.singlePass) {
|
|
184
193
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
185
194
|
globalThis.__hadarsContext = context;
|
|
186
195
|
try {
|
|
@@ -190,6 +199,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
190
199
|
globalThis.__hadarsContext = null;
|
|
191
200
|
}
|
|
192
201
|
} else {
|
|
202
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
203
|
+
globalThis.__hadarsContext = context;
|
|
193
204
|
try {
|
|
194
205
|
await renderPreflight(element);
|
|
195
206
|
} finally {
|
package/dist/cli.js
CHANGED
|
@@ -1228,7 +1228,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1228
1228
|
globalThis.__hadarsContext = context;
|
|
1229
1229
|
const element = createElement(App, props);
|
|
1230
1230
|
let bodyHtml = null;
|
|
1231
|
-
if (opts.
|
|
1231
|
+
if (opts.dataOnly) {
|
|
1232
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1233
|
+
globalThis.__hadarsContext = context;
|
|
1234
|
+
try {
|
|
1235
|
+
await renderPreflight(element);
|
|
1236
|
+
} finally {
|
|
1237
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1238
|
+
globalThis.__hadarsContext = null;
|
|
1239
|
+
}
|
|
1240
|
+
} else if (opts.singlePass) {
|
|
1232
1241
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1233
1242
|
globalThis.__hadarsContext = context;
|
|
1234
1243
|
try {
|
|
@@ -1238,6 +1247,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1238
1247
|
globalThis.__hadarsContext = null;
|
|
1239
1248
|
}
|
|
1240
1249
|
} else {
|
|
1250
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1251
|
+
globalThis.__hadarsContext = context;
|
|
1241
1252
|
try {
|
|
1242
1253
|
await renderPreflight(element);
|
|
1243
1254
|
} finally {
|
|
@@ -1760,6 +1771,15 @@ async function tryServeFile(filePath) {
|
|
|
1760
1771
|
return null;
|
|
1761
1772
|
}
|
|
1762
1773
|
}
|
|
1774
|
+
var _notFound = new Set;
|
|
1775
|
+
async function tryServeFileCached(filePath) {
|
|
1776
|
+
if (_notFound.has(filePath))
|
|
1777
|
+
return null;
|
|
1778
|
+
const res = await tryServeFile(filePath);
|
|
1779
|
+
if (!res)
|
|
1780
|
+
_notFound.add(filePath);
|
|
1781
|
+
return res;
|
|
1782
|
+
}
|
|
1763
1783
|
|
|
1764
1784
|
// src/build.ts
|
|
1765
1785
|
import { RspackDevServer } from "@rspack/dev-server";
|
|
@@ -1783,10 +1803,11 @@ function buildSsrResponse(head, status, getAppBody, finalize, getPrecontentHtml)
|
|
|
1783
1803
|
async start(controller) {
|
|
1784
1804
|
try {
|
|
1785
1805
|
const [precontentHtml, postContent] = precontentResult instanceof Promise ? await precontentResult : precontentResult;
|
|
1806
|
+
const finalizePromise = finalize();
|
|
1786
1807
|
controller.enqueue(encoder.encode(precontentHtml));
|
|
1787
1808
|
const bodyHtml = await getAppBody();
|
|
1788
1809
|
controller.enqueue(encoder.encode(`<div id="app">${bodyHtml}</div>`));
|
|
1789
|
-
const { clientProps } = await
|
|
1810
|
+
const { clientProps } = await finalizePromise;
|
|
1790
1811
|
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1791
1812
|
controller.enqueue(encoder.encode(`<script id="hadars" type="application/json">${scriptContent}</script>` + postContent));
|
|
1792
1813
|
controller.close();
|
|
@@ -2742,6 +2763,7 @@ var dev = async (options) => {
|
|
|
2742
2763
|
} catch (e) {}
|
|
2743
2764
|
})();
|
|
2744
2765
|
const getPrecontentHtml = makePrecontentHtmlGetter(readyPromise.then(() => fs.readFile(pathMod2.join(__dirname3, StaticPath, "out.html"), "utf-8")));
|
|
2766
|
+
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2745
2767
|
await serve(port, async (req, ctx) => {
|
|
2746
2768
|
await readyPromise;
|
|
2747
2769
|
const request = parseRequest(req);
|
|
@@ -2762,11 +2784,10 @@ var dev = async (options) => {
|
|
|
2762
2784
|
return proxied;
|
|
2763
2785
|
const url = new URL(request.url);
|
|
2764
2786
|
const path2 = url.pathname;
|
|
2765
|
-
const staticRes = await
|
|
2787
|
+
const staticRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, path2));
|
|
2766
2788
|
if (staticRes)
|
|
2767
2789
|
return staticRes;
|
|
2768
|
-
const
|
|
2769
|
-
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2790
|
+
const projectRes = await tryServeFileCached(pathMod2.join(projectStaticPath, path2));
|
|
2770
2791
|
if (projectRes)
|
|
2771
2792
|
return projectRes;
|
|
2772
2793
|
const ssrComponentPath = pathMod2.join(__dirname3, HadarsFolder, SSR_FILENAME);
|
|
@@ -2782,6 +2803,7 @@ var dev = async (options) => {
|
|
|
2782
2803
|
getFinalProps
|
|
2783
2804
|
} = cachedSsrModule;
|
|
2784
2805
|
globalThis.__hadarsGraphQL = devStaticCtx?.graphql;
|
|
2806
|
+
const isDataOnly = request.headers.get("Accept") === "application/json";
|
|
2785
2807
|
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2786
2808
|
document: {
|
|
2787
2809
|
body: Component,
|
|
@@ -2790,9 +2812,10 @@ var dev = async (options) => {
|
|
|
2790
2812
|
getFinalProps
|
|
2791
2813
|
},
|
|
2792
2814
|
staticCtx: devStaticCtx,
|
|
2793
|
-
singlePass:
|
|
2815
|
+
singlePass: !isDataOnly,
|
|
2816
|
+
dataOnly: isDataOnly
|
|
2794
2817
|
});
|
|
2795
|
-
if (
|
|
2818
|
+
if (isDataOnly) {
|
|
2796
2819
|
const { clientProps } = await finalize();
|
|
2797
2820
|
const serverData = clientProps.__serverData ?? {};
|
|
2798
2821
|
return new Response(JSON.stringify({ serverData }), {
|
|
@@ -2899,6 +2922,7 @@ var run = async (options) => {
|
|
|
2899
2922
|
console.log(`[hadars] SSR render pool: ${workers} worker threads`);
|
|
2900
2923
|
}
|
|
2901
2924
|
const getPrecontentHtml = makePrecontentHtmlGetter(fs.readFile(pathMod2.join(__dirname3, StaticPath, "out.html"), "utf-8"));
|
|
2925
|
+
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2902
2926
|
const componentPath = pathToFileURL(pathMod2.resolve(__dirname3, HadarsFolder, SSR_FILENAME)).href;
|
|
2903
2927
|
const ssrModulePromise = import(componentPath);
|
|
2904
2928
|
const runHandler = async (req, ctx) => {
|
|
@@ -2915,16 +2939,15 @@ var run = async (options) => {
|
|
|
2915
2939
|
return proxied;
|
|
2916
2940
|
const url = new URL(request.url);
|
|
2917
2941
|
const path2 = url.pathname;
|
|
2918
|
-
const staticRes = await
|
|
2942
|
+
const staticRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, path2));
|
|
2919
2943
|
if (staticRes)
|
|
2920
2944
|
return staticRes;
|
|
2921
|
-
const
|
|
2922
|
-
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2945
|
+
const projectRes = await tryServeFileCached(pathMod2.join(projectStaticPath, path2));
|
|
2923
2946
|
if (projectRes)
|
|
2924
2947
|
return projectRes;
|
|
2925
2948
|
const routeClean = path2.replace(/(^\/|\/$)/g, "");
|
|
2926
2949
|
if (routeClean) {
|
|
2927
|
-
const routeRes = await
|
|
2950
|
+
const routeRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, routeClean, "index.html"));
|
|
2928
2951
|
if (routeRes)
|
|
2929
2952
|
return routeRes;
|
|
2930
2953
|
}
|
|
@@ -2943,6 +2966,7 @@ var run = async (options) => {
|
|
|
2943
2966
|
status: wStatus
|
|
2944
2967
|
});
|
|
2945
2968
|
}
|
|
2969
|
+
const isDataOnly = request.headers.get("Accept") === "application/json";
|
|
2946
2970
|
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2947
2971
|
document: {
|
|
2948
2972
|
body: Component,
|
|
@@ -2950,9 +2974,10 @@ var run = async (options) => {
|
|
|
2950
2974
|
getInitProps,
|
|
2951
2975
|
getFinalProps
|
|
2952
2976
|
},
|
|
2953
|
-
singlePass:
|
|
2977
|
+
singlePass: !isDataOnly,
|
|
2978
|
+
dataOnly: isDataOnly
|
|
2954
2979
|
});
|
|
2955
|
-
if (
|
|
2980
|
+
if (isDataOnly) {
|
|
2956
2981
|
const { clientProps } = await finalize();
|
|
2957
2982
|
const serverData = clientProps.__serverData ?? {};
|
|
2958
2983
|
return new Response(JSON.stringify({ serverData }), {
|
package/dist/cloudflare.cjs
CHANGED
|
@@ -1231,7 +1231,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1231
1231
|
globalThis.__hadarsContext = context;
|
|
1232
1232
|
const element = createElement(App, props);
|
|
1233
1233
|
let bodyHtml = null;
|
|
1234
|
-
if (opts.
|
|
1234
|
+
if (opts.dataOnly) {
|
|
1235
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1236
|
+
globalThis.__hadarsContext = context;
|
|
1237
|
+
try {
|
|
1238
|
+
await renderPreflight(element);
|
|
1239
|
+
} finally {
|
|
1240
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1241
|
+
globalThis.__hadarsContext = null;
|
|
1242
|
+
}
|
|
1243
|
+
} else if (opts.singlePass) {
|
|
1235
1244
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1236
1245
|
globalThis.__hadarsContext = context;
|
|
1237
1246
|
try {
|
|
@@ -1241,6 +1250,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1241
1250
|
globalThis.__hadarsContext = null;
|
|
1242
1251
|
}
|
|
1243
1252
|
} else {
|
|
1253
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1254
|
+
globalThis.__hadarsContext = context;
|
|
1244
1255
|
try {
|
|
1245
1256
|
await renderPreflight(element);
|
|
1246
1257
|
} finally {
|
package/dist/cloudflare.js
CHANGED
package/dist/lambda.cjs
CHANGED
|
@@ -1271,7 +1271,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1271
1271
|
globalThis.__hadarsContext = context;
|
|
1272
1272
|
const element = createElement(App, props);
|
|
1273
1273
|
let bodyHtml = null;
|
|
1274
|
-
if (opts.
|
|
1274
|
+
if (opts.dataOnly) {
|
|
1275
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1276
|
+
globalThis.__hadarsContext = context;
|
|
1277
|
+
try {
|
|
1278
|
+
await renderPreflight(element);
|
|
1279
|
+
} finally {
|
|
1280
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1281
|
+
globalThis.__hadarsContext = null;
|
|
1282
|
+
}
|
|
1283
|
+
} else if (opts.singlePass) {
|
|
1275
1284
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1276
1285
|
globalThis.__hadarsContext = context;
|
|
1277
1286
|
try {
|
|
@@ -1281,6 +1290,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1281
1290
|
globalThis.__hadarsContext = null;
|
|
1282
1291
|
}
|
|
1283
1292
|
} else {
|
|
1293
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1294
|
+
globalThis.__hadarsContext = context;
|
|
1284
1295
|
try {
|
|
1285
1296
|
await renderPreflight(element);
|
|
1286
1297
|
} finally {
|
package/dist/lambda.js
CHANGED