@wular/pnext 0.0.2 → 0.0.4

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.
Files changed (64) hide show
  1. package/README.md +76 -20
  2. package/package.json +3 -2
  3. package/reference/data/bench.json +513 -0
  4. package/reference/performance.md +75 -48
  5. package/src/api/router/runtime.ts +60 -21
  6. package/src/cache/context.ts +4 -1
  7. package/src/cli/build.ts +37 -5
  8. package/src/cli/dev.ts +6 -0
  9. package/src/cli/index.ts +17 -3
  10. package/src/cli/request-pipeline.ts +1340 -0
  11. package/src/cli/server-entry.ts +180 -0
  12. package/src/cli/start.ts +39 -1311
  13. package/src/client/build.ts +59 -20
  14. package/src/client/chunk-fold.ts +40 -0
  15. package/src/client/compat-surface.ts +175 -0
  16. package/src/client/entry.ts +67 -52
  17. package/src/compat/actions/action-client.ts +8 -1
  18. package/src/compat/actions/action-dispatch.ts +11 -1
  19. package/src/compat/actions/discovery.ts +23 -6
  20. package/src/compat/bundler/optimize-package-imports.ts +5 -1
  21. package/src/compat/bundler/worker.ts +2 -1
  22. package/src/compat/client/errors/bare-boundary.ts +32 -0
  23. package/src/compat/client/errors/error-boundary.ts +1 -15
  24. package/src/compat/client/errors/primitive-throw.ts +16 -0
  25. package/src/compat/client/link-status.ts +1 -1
  26. package/src/compat/css/lightningcss.ts +2 -1
  27. package/src/compat/css/modules.ts +4 -3
  28. package/src/compat/lifecycle/instrumentation-client.ts +1 -1
  29. package/src/compat/lifecycle/instrumentation.ts +5 -2
  30. package/src/compat/next/config-loader.ts +33 -5
  31. package/src/compat/next/dynamic.tsx +9 -5
  32. package/src/compat/next/link-validation-transform.ts +5 -1
  33. package/src/compat/next/link.tsx +51 -58
  34. package/src/compat/pages/client-plugin.ts +2 -1
  35. package/src/compat/react/action-state.ts +159 -0
  36. package/src/compat/react/client-lite.ts +74 -0
  37. package/src/compat/react/hooks-extra.ts +92 -0
  38. package/src/compat/react/parity.ts +128 -0
  39. package/src/compat/react/preact.ts +33 -420
  40. package/src/compat/react/server-inserted-html.ts +14 -7
  41. package/src/compat/react/use.ts +72 -0
  42. package/src/compat/register/actions.ts +27 -7
  43. package/src/compat/register/segment.ts +16 -6
  44. package/src/config.ts +15 -1
  45. package/src/css/build.ts +13 -2
  46. package/src/dev/imports.ts +34 -5
  47. package/src/dev/module-cache.ts +19 -0
  48. package/src/dev/module-transform.ts +7 -1
  49. package/src/dev/server.ts +91 -22
  50. package/src/dynamic/source.ts +36 -27
  51. package/src/ppr.ts +5 -4
  52. package/src/proxy.ts +5 -1
  53. package/src/render/island-context.ts +21 -3
  54. package/src/render/renderer.ts +102 -26
  55. package/src/resolve/engine.ts +12 -2
  56. package/src/resolve/scan-facts.ts +239 -1
  57. package/src/routing/href.ts +4 -5
  58. package/src/routing/routes.ts +26 -41
  59. package/src/runtime/server.ts +8 -4
  60. package/src/runtime/vendor.ts +1 -1
  61. package/src/typegen.ts +3 -3
  62. package/src/utils/esbuild.ts +58 -0
  63. package/src/utils/fs.ts +14 -2
  64. package/src/utils/native-require.ts +28 -0
package/README.md CHANGED
@@ -2,12 +2,10 @@
2
2
 
3
3
  # pnext
4
4
 
5
- **A fast little framework for server-first React apps, fully compatible with Next.js.**
5
+ **A fast little framework for server-first React apps, fully compatible with Next.js.**[<sup>1</sup>](./reference/compat.md)
6
6
 
7
7
  </div>
8
8
 
9
- Server-rendered pages ship **0 KB** of JavaScript — **~1 KB gzip** with client-side navigation and prefetching. Interactive pages hydrate on Preact for **~7.5 KB** of framework, or **~12.5 KB** with React compatibility. Everything is instant: the dev server starts **~3× faster** than Next's on **~4× less memory**, and production builds run **4.5–10× faster**. The Next.js App Router compatibility is validated against Next's own test suite, 4,400+ assertions passing.
10
-
11
9
  ## Getting started
12
10
 
13
11
  A new app:
@@ -16,7 +14,7 @@ A new app:
16
14
  bunx @wular/pnext create my-app
17
15
  ```
18
16
 
19
- Migrating a Next.js app rewrites scripts and config in place, scans your source, and reports anything that needs a look (never edits your code):
17
+ Migrating a Next.js app? This rewrites scripts and config in place, scans your source, and reports anything that needs a look (it never edits your code):
20
18
 
21
19
  ```sh
22
20
  bunx @wular/pnext migrate
@@ -24,27 +22,85 @@ bunx @wular/pnext migrate
24
22
 
25
23
  Or by hand: `bun add -d @wular/pnext`, then `pnext dev`.
26
24
 
27
- Adoption is incremental: core pnext is based on pure Preact, `compat.react` runs React components and libraries on it, and `compat.next` runs a whole Next.js App Router app unchanged — start anywhere on that ladder and move when it suits you. See [Compatibility](./reference/compat.md).
25
+ ## Incremental by design
26
+
27
+ Server-rendered pages ship **0 KB** of JavaScript, or **~1 KB gzip** if you want client-side navigation and prefetching. Interactive pages hydrate on Preact for **~7.5 KB** of framework, **~12.5 KB** with React compatibility. And everything is instant: the first page in dev renders **11–13.5× faster** than Next's on **3.4–3.8× less memory**, and production builds run **7–10.5× faster**. See [Performance](./reference/performance.md).
28
+
29
+ Core pnext is pure Preact. `compat.react` runs React components and libraries on it, and `compat.next` runs a whole Next.js App Router app unchanged. Start anywhere on that ladder and move when it suits you. The App Router compatibility is validated against Next's own test suite (4,400+ assertions passing). The `pages/` folder is not supported, and neither are private internal utilities of Next.js or React. See [Compatibility](./reference/compat.md).
30
+
31
+ ## A quick tour
32
+
33
+ ### Your first page
34
+
35
+ Routes live in `app/`. A `page.tsx` is a Server Component by default. It runs only on the server, so it can be async and talk to your database, filesystem, or internal services directly. None of that code reaches the browser:
36
+
37
+ ```tsx
38
+ // app/posts/[id]/page.tsx
39
+ import type { PageProps } from "#gen/app/posts/[id]/page";
40
+
41
+ export default async function Page({ params }: PageProps) {
42
+ const { id } = await params;
43
+ const post = await db.post.findUnique({ where: { id } });
44
+ return (
45
+ <article>
46
+ <h1>{post.title}</h1>
47
+ <p>{post.body}</p>
48
+ </article>
49
+ );
50
+ }
51
+ ```
52
+
53
+ This page ships **0 KB** of JavaScript. Layouts work the same way: the root `layout.tsx` owns `<html>` and `<body>` and can export `metadata`.
54
+
55
+ ### Adding interactivity
28
56
 
29
- ## Measured against Next.js
57
+ Mark a component with `"use client"` where you need state, effects, or event handlers. Server Components render it into the page, and only that island hydrates in the browser:
30
58
 
31
- The same fixture source runs under both frameworks; `bun bench` measures them side by side and rewrites [`reference/performance.md`](./reference/performance.md) with your machine's absolute numbers. The ranges below span the fixtures — hello-world, an SSR site, and a mid-size admin dashboard (30 routes, 18 client islands):
59
+ ```tsx
60
+ // app/counter.tsx
61
+ "use client";
62
+ import { useState } from "preact/hooks";
32
63
 
33
- | | pnext vs Next.js |
34
- | --------------------------- | ---------------------------------: |
35
- | Dev server ready | **2.5–3× faster** |
36
- | First page, cold | **6.5–13× faster** |
37
- | Warm request | **4–7.5× faster** |
38
- | HMR save → visible | **1–2.5× faster** |
39
- | Production build | **4.5–10× faster** |
40
- | Dev server memory | **3.5–4× less** |
41
- | Build peak memory | **3–4× less** |
42
- | Framework install size | **42× smaller** (6.7 MB vs 286 MB) |
43
- | First-page client JS (gzip) | **6–65× less** |
64
+ export function Counter({ initial }: { initial: number }) {
65
+ const [count, setCount] = useState(initial);
66
+ return <button onClick={() => setCount(count + 1)}>Count {count}</button>;
67
+ }
68
+ ```
69
+
70
+ Client Components hydrate on Preact for ~7.5 KB of framework, or ~12.5 KB with [`compat.react`](./reference/compat.md) if you want to run React components and libraries unchanged. Offscreen islands can stay out of the initial bundle entirely with `dynamic({ load: 'visible' })`.
71
+
72
+ ### Streaming
73
+
74
+ Wrap slow server work in `<Suspense>`. The shell streams immediately and the content follows when it's ready:
75
+
76
+ ```tsx
77
+ import { Suspense } from "@wular/pnext";
78
+
79
+ export default function Page() {
80
+ return (
81
+ <Suspense fallback={<p>Loading comments…</p>}>
82
+ <Comments />
83
+ </Suspense>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ### APIs and everything else
89
+
90
+ A `route.ts` file is an HTTP handler:
91
+
92
+ ```ts
93
+ // app/api/users/route.ts
94
+ export async function GET(request: NextRequest) {
95
+ return Response.json(await listUsers());
96
+ }
97
+ ```
44
98
 
45
- Nothing is prebundled — the dev server compiles what a request needs and caches it content-addressed, which is why readiness doesn't scale with app size. One metric goes the other way: the production server idles ~10 MB heavier than Next's (~113 vs ~101 MB, Bun's runtime baseline) while answering warm requests up to 2× faster.
99
+ - `proxy.ts` runs before route matching.
100
+ - `loading.tsx`, `error.tsx`, and `not-found.tsx` define per-segment fallbacks.
101
+ - `pnext build` emits static HTML for routes that never read the request, and a server for the ones that do. `pnext start` serves it.
46
102
 
47
- ## Learn
103
+ ## Learn more
48
104
 
49
105
  Apps are file-routed from `app/`: `page.tsx` and `layout.tsx` are Server Components, `route.ts` files are HTTP handlers, `public/` is served from `/`. The reference covers the rest:
50
106
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wular/pnext",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pnext": "bin/pnext"
@@ -23,7 +23,8 @@
23
23
  "./link": "./src/api/link.tsx",
24
24
  "./navigation": "./src/api/navigation.ts",
25
25
  "./navigation/client": "./src/api/client-navigation.ts",
26
- "./server": "./src/api/server.ts"
26
+ "./server": "./src/api/server.ts",
27
+ "./config/*": "./config/*"
27
28
  },
28
29
  "scripts": {
29
30
  "lint": "bun scripts/check-compat-boundary.ts && eslint . --max-warnings 0 && tsc --noEmit",
@@ -0,0 +1,513 @@
1
+ {
2
+ "run": {
3
+ "date": "2026-08-20",
4
+ "machine": "CI — Blacksmith 4 vCPU (Intel Xeon), 16 GB RAM, Ubuntu 22.04 x64",
5
+ "bun": "1.3.10",
6
+ "next": "16.2.12",
7
+ "runs": "5 per metric (first discarded), medians reported"
8
+ },
9
+ "fixtures": [
10
+ {
11
+ "id": "hello",
12
+ "label": "hello-world",
13
+ "blurb": "A single page."
14
+ },
15
+ {
16
+ "id": "ssr",
17
+ "label": "ssr",
18
+ "blurb": "A server-rendered site."
19
+ },
20
+ {
21
+ "id": "dashboard",
22
+ "label": "dashboard",
23
+ "blurb": "A mid-size admin app — 30 routes, 18 client islands."
24
+ }
25
+ ],
26
+ "metrics": [
27
+ {
28
+ "id": "dev-ready",
29
+ "label": "Dev server ready",
30
+ "category": "dev",
31
+ "phase": "cold",
32
+ "rows": {
33
+ "hello": [
34
+ 56.4,
35
+ "56.4 ms",
36
+ 212.3,
37
+ "212.3 ms",
38
+ 3.76
39
+ ],
40
+ "ssr": [
41
+ 56,
42
+ "56.0 ms",
43
+ 212.8,
44
+ "212.8 ms",
45
+ 3.8
46
+ ],
47
+ "dashboard": [
48
+ 57.1,
49
+ "57.1 ms",
50
+ 246.4,
51
+ "246.4 ms",
52
+ 4.31
53
+ ]
54
+ }
55
+ },
56
+ {
57
+ "id": "dev-first-page",
58
+ "label": "Dev first page HTML",
59
+ "category": "dev",
60
+ "phase": "cold",
61
+ "rows": {
62
+ "hello": [
63
+ 79.9,
64
+ "79.9 ms",
65
+ 993.5,
66
+ "993.5 ms",
67
+ 12.44
68
+ ],
69
+ "ssr": [
70
+ 93.5,
71
+ "93.5 ms",
72
+ 1043.3,
73
+ "1043.3 ms",
74
+ 11.16
75
+ ],
76
+ "dashboard": [
77
+ 127,
78
+ "127.0 ms",
79
+ 1285.8,
80
+ "1285.8 ms",
81
+ 10.12
82
+ ]
83
+ }
84
+ },
85
+ {
86
+ "id": "dev-warm",
87
+ "label": "Dev warm request (p50 of 7)",
88
+ "category": "dev",
89
+ "phase": "warm",
90
+ "rows": {
91
+ "hello": [
92
+ 3,
93
+ "3.0 ms",
94
+ 14,
95
+ "14.0 ms",
96
+ 4.69
97
+ ],
98
+ "ssr": [
99
+ 16.5,
100
+ "16.5 ms",
101
+ 26.4,
102
+ "26.4 ms",
103
+ 1.6
104
+ ],
105
+ "dashboard": [
106
+ 21.6,
107
+ "21.6 ms",
108
+ 34.1,
109
+ "34.1 ms",
110
+ 1.58
111
+ ]
112
+ }
113
+ },
114
+ {
115
+ "id": "hmr",
116
+ "label": "HMR save → visible",
117
+ "category": "dev",
118
+ "phase": "warm",
119
+ "rows": {
120
+ "hello": [
121
+ 21.9,
122
+ "21.9 ms",
123
+ 44.8,
124
+ "44.8 ms",
125
+ 2.04
126
+ ],
127
+ "ssr": [
128
+ 264.3,
129
+ "264.3 ms",
130
+ 68.3,
131
+ "68.3 ms",
132
+ 0.26
133
+ ],
134
+ "dashboard": [
135
+ 300.4,
136
+ "300.4 ms",
137
+ 97.6,
138
+ "97.6 ms",
139
+ 0.32
140
+ ]
141
+ }
142
+ },
143
+ {
144
+ "id": "build-wall",
145
+ "label": "Production build (wall)",
146
+ "category": "build",
147
+ "phase": "cold",
148
+ "rows": {
149
+ "hello": [
150
+ 291.3,
151
+ "291.3 ms",
152
+ 2569.4,
153
+ "2569.4 ms",
154
+ 8.82
155
+ ],
156
+ "ssr": [
157
+ 310.5,
158
+ "310.5 ms",
159
+ 2738.8,
160
+ "2738.8 ms",
161
+ 8.82
162
+ ],
163
+ "dashboard": [
164
+ 637.5,
165
+ "637.5 ms",
166
+ 4566.3,
167
+ "4566.3 ms",
168
+ 7.16
169
+ ]
170
+ }
171
+ },
172
+ {
173
+ "id": "prod-start",
174
+ "label": "Prod start (ready)",
175
+ "category": "build",
176
+ "phase": "cold",
177
+ "rows": {
178
+ "hello": [
179
+ 60.7,
180
+ "60.7 ms",
181
+ 110.9,
182
+ "110.9 ms",
183
+ 1.83
184
+ ],
185
+ "ssr": [
186
+ 57.1,
187
+ "57.1 ms",
188
+ 105.5,
189
+ "105.5 ms",
190
+ 1.85
191
+ ],
192
+ "dashboard": [
193
+ 55.6,
194
+ "55.6 ms",
195
+ 128.8,
196
+ "128.8 ms",
197
+ 2.32
198
+ ]
199
+ }
200
+ },
201
+ {
202
+ "id": "prod-warm",
203
+ "label": "Prod warm request (p50 of 7)",
204
+ "category": "build",
205
+ "phase": "warm",
206
+ "rows": {
207
+ "hello": [
208
+ 0.6,
209
+ "0.6 ms",
210
+ 1.2,
211
+ "1.2 ms",
212
+ 2.05
213
+ ],
214
+ "ssr": [
215
+ 0.5,
216
+ "0.5 ms",
217
+ 1.3,
218
+ "1.3 ms",
219
+ 2.5
220
+ ],
221
+ "dashboard": [
222
+ 0.5,
223
+ "0.5 ms",
224
+ 1.7,
225
+ "1.7 ms",
226
+ 3.41
227
+ ]
228
+ }
229
+ },
230
+ {
231
+ "id": "dev-rss",
232
+ "label": "Dev server RSS (ready + 7 warm)",
233
+ "category": "memory",
234
+ "phase": "warm",
235
+ "rows": {
236
+ "hello": [
237
+ 130.8,
238
+ "130.8 MB",
239
+ 536.4,
240
+ "536.4 MB",
241
+ 4.1
242
+ ],
243
+ "ssr": [
244
+ 151.3,
245
+ "151.3 MB",
246
+ 553.6,
247
+ "553.6 MB",
248
+ 3.66
249
+ ],
250
+ "dashboard": [
251
+ 168.6,
252
+ "168.6 MB",
253
+ 577.1,
254
+ "577.1 MB",
255
+ 3.42
256
+ ]
257
+ }
258
+ },
259
+ {
260
+ "id": "build-rss",
261
+ "label": "Prod build peak RSS",
262
+ "category": "memory",
263
+ "phase": "cold",
264
+ "rows": {
265
+ "hello": [
266
+ 124.2,
267
+ "124.2 MB",
268
+ 455.8,
269
+ "455.8 MB",
270
+ 3.67
271
+ ],
272
+ "ssr": [
273
+ 136.8,
274
+ "136.8 MB",
275
+ 456.6,
276
+ "456.6 MB",
277
+ 3.34
278
+ ],
279
+ "dashboard": [
280
+ 188,
281
+ "188.0 MB",
282
+ 569,
283
+ "569.0 MB",
284
+ 3.03
285
+ ]
286
+ }
287
+ },
288
+ {
289
+ "id": "prod-rss",
290
+ "label": "Prod server RSS (ready + 7 warm)",
291
+ "category": "memory",
292
+ "phase": "warm",
293
+ "rows": {
294
+ "hello": [
295
+ 85.2,
296
+ "85.2 MB",
297
+ 85.7,
298
+ "85.7 MB",
299
+ 1.01
300
+ ],
301
+ "ssr": [
302
+ 86,
303
+ "86.0 MB",
304
+ 85.9,
305
+ "85.9 MB",
306
+ 1
307
+ ],
308
+ "dashboard": [
309
+ 87.3,
310
+ "87.3 MB",
311
+ 90.6,
312
+ "90.6 MB",
313
+ 1.04
314
+ ]
315
+ }
316
+ },
317
+ {
318
+ "id": "install",
319
+ "label": "Framework install size",
320
+ "category": "payload",
321
+ "phase": "static",
322
+ "rows": {
323
+ "hello": [
324
+ 7.1,
325
+ "7.1 MB",
326
+ 420.7,
327
+ "420.7 MB",
328
+ 59.14
329
+ ],
330
+ "ssr": [
331
+ 7.1,
332
+ "7.1 MB",
333
+ 420.7,
334
+ "420.7 MB",
335
+ 59.14
336
+ ],
337
+ "dashboard": [
338
+ 7.1,
339
+ "7.1 MB",
340
+ 420.7,
341
+ "420.7 MB",
342
+ 59.14
343
+ ]
344
+ }
345
+ },
346
+ {
347
+ "id": "js-gzip",
348
+ "label": "First-page client JS (gzip)",
349
+ "category": "payload",
350
+ "phase": "static",
351
+ "rows": {
352
+ "hello": [
353
+ 2.19,
354
+ "2.19 KB",
355
+ 141.78,
356
+ "141.78 KB",
357
+ 64.67
358
+ ],
359
+ "ssr": [
360
+ 11.39,
361
+ "11.39 KB",
362
+ 142.03,
363
+ "142.03 KB",
364
+ 12.47
365
+ ],
366
+ "dashboard": [
367
+ 15.26,
368
+ "15.26 KB",
369
+ 144.85,
370
+ "144.85 KB",
371
+ 9.5
372
+ ]
373
+ }
374
+ },
375
+ {
376
+ "id": "js-raw",
377
+ "label": "First-page client JS (raw)",
378
+ "category": "payload",
379
+ "phase": "static",
380
+ "rows": {
381
+ "hello": [
382
+ 4.43,
383
+ "4.43 KB",
384
+ 502.47,
385
+ "502.47 KB",
386
+ 113.36
387
+ ],
388
+ "ssr": [
389
+ 27.36,
390
+ "27.36 KB",
391
+ 502.78,
392
+ "502.78 KB",
393
+ 18.37
394
+ ],
395
+ "dashboard": [
396
+ 38.51,
397
+ "38.51 KB",
398
+ 507.42,
399
+ "507.42 KB",
400
+ 13.18
401
+ ]
402
+ }
403
+ },
404
+ {
405
+ "id": "js-files",
406
+ "label": "First-page JS files",
407
+ "category": "payload",
408
+ "phase": "static",
409
+ "rows": {
410
+ "hello": [
411
+ 3,
412
+ "3",
413
+ 5,
414
+ "5",
415
+ 1.67
416
+ ],
417
+ "ssr": [
418
+ 4,
419
+ "4",
420
+ 6,
421
+ "6",
422
+ 1.5
423
+ ],
424
+ "dashboard": [
425
+ 6,
426
+ "6",
427
+ 9,
428
+ "9",
429
+ 1.5
430
+ ]
431
+ }
432
+ },
433
+ {
434
+ "id": "zero-island",
435
+ "label": "Zero-island route client JS",
436
+ "category": "payload",
437
+ "phase": "static",
438
+ "rows": {
439
+ "hello": [
440
+ 4.43,
441
+ "4.43 KB",
442
+ 502.47,
443
+ "502.47 KB",
444
+ 113.36
445
+ ],
446
+ "ssr": [
447
+ 4.46,
448
+ "4.46 KB",
449
+ 502.47,
450
+ "502.47 KB",
451
+ 112.56
452
+ ]
453
+ }
454
+ }
455
+ ],
456
+ "headlines": [
457
+ {
458
+ "label": "Dev server ready",
459
+ "direction": "faster",
460
+ "value": "3.8–4.3×"
461
+ },
462
+ {
463
+ "label": "First page, cold",
464
+ "direction": "faster",
465
+ "value": "10–12×"
466
+ },
467
+ {
468
+ "label": "Warm request (dev)",
469
+ "direction": "faster",
470
+ "value": "1.6–4.7×"
471
+ },
472
+ {
473
+ "label": "Production build",
474
+ "direction": "faster",
475
+ "value": "7.2–8.8×"
476
+ },
477
+ {
478
+ "label": "Warm request (prod)",
479
+ "direction": "faster",
480
+ "value": "2–3.4×"
481
+ },
482
+ {
483
+ "label": "Dev server memory",
484
+ "direction": "less",
485
+ "value": "3.4–4.1×"
486
+ },
487
+ {
488
+ "label": "First-page client JS (gzip)",
489
+ "direction": "less",
490
+ "value": "9.5–65×"
491
+ },
492
+ {
493
+ "label": "Framework install size",
494
+ "direction": "smaller",
495
+ "value": "59×",
496
+ "detail": "7.1 MB vs 420.7 MB"
497
+ }
498
+ ],
499
+ "clientRuntimes": [
500
+ {
501
+ "name": "router-prefetch-only",
502
+ "raw": "473 B",
503
+ "gzip": "348 B",
504
+ "brotli": "283 B"
505
+ },
506
+ {
507
+ "name": "combined-router-hydrator",
508
+ "raw": "10.47 KB",
509
+ "gzip": "4.47 KB",
510
+ "brotli": "4.07 KB"
511
+ }
512
+ ]
513
+ }