koa-classic-server 3.0.0 → 3.1.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 +44 -120
- package/index.cjs +236 -21
- package/package.json +10 -5
- package/.github/workflows/npm-publish.yml +0 -98
- package/CLAUDE.md +0 -101
- package/__tests__/benchmark-results-baseline-v1.2.0.txt +0 -354
- package/__tests__/benchmark-results-optimized-v2.0.0.txt +0 -354
- package/__tests__/benchmark-results-v3.0.0.txt +0 -372
- package/__tests__/benchmark.js +0 -239
- package/__tests__/caching-headers.test.js +0 -556
- package/__tests__/compression-fixtures/data.json +0 -1
- package/__tests__/compression-fixtures/large.txt +0 -1
- package/__tests__/compression-fixtures/small.txt +0 -1
- package/__tests__/compression.test.js +0 -284
- package/__tests__/customTest/README.md +0 -6
- package/__tests__/customTest/loadConfig.util.js +0 -41
- package/__tests__/customTest/serversToLoad.util.js +0 -93
- package/__tests__/demo-regex-index.js +0 -140
- package/__tests__/deprecation-warnings.test.js +0 -105
- package/__tests__/directory-sorting-links.test.js +0 -135
- package/__tests__/dt-unknown.test.js +0 -635
- package/__tests__/ejs.test.js +0 -299
- package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
- package/__tests__/hidden-fixtures/.env +0 -2
- package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
- package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
- package/__tests__/hidden-fixtures/data.key +0 -1
- package/__tests__/hidden-fixtures/file.secret +0 -1
- package/__tests__/hidden-fixtures/index.html +0 -1
- package/__tests__/hidden-fixtures/normal.txt +0 -1
- package/__tests__/hidden-fixtures/subdir/.env +0 -1
- package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
- package/__tests__/hidden-option.test.js +0 -407
- package/__tests__/hideExtension.test.js +0 -607
- package/__tests__/index-option.test.js +0 -449
- package/__tests__/index.test.js +0 -345
- package/__tests__/listing.test.js +0 -437
- package/__tests__/logger.test.js +0 -232
- package/__tests__/performance.test.js +0 -370
- package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
- package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
- package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
- package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
- package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
- package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
- package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
- package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
- package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
- package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
- package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
- package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
- package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
- package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
- package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
- package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
- package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
- package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
- package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
- package/__tests__/publicWwwTest/index.html +0 -11
- package/__tests__/publicWwwTest/prova file .txt +0 -2
- package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
- package/__tests__/publicWwwTest/test-page.html +0 -1
- package/__tests__/publicWwwTest/test.txt +0 -1
- package/__tests__/range-fixtures/sample.txt +0 -1
- package/__tests__/range.test.js +0 -223
- package/__tests__/security-headers.test.js +0 -165
- package/__tests__/security.test.js +0 -322
- package/__tests__/server-cache-fixtures/large.txt +0 -1
- package/__tests__/server-cache-fixtures/small.txt +0 -1
- package/__tests__/server-cache.test.js +0 -594
- package/__tests__/setup-benchmark.js +0 -178
- package/__tests__/symlink.test.js +0 -441
- package/__tests__/template-timeout.test.js +0 -321
- package/__tests__/test-regex-quick.js +0 -158
- package/__tests__/useOriginalUrl.test.js +0 -213
- package/docs/ACTION_PLAN.md +0 -293
- package/docs/BENCHMARKS.md +0 -317
- package/docs/CHANGELOG.md +0 -880
- package/docs/CODE_REVIEW.md +0 -300
- package/docs/DEBUG_REPORT.md +0 -593
- package/docs/DOCUMENTATION.md +0 -1864
- package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
- package/docs/FLOW_DIAGRAM.md +0 -954
- package/docs/INDEX_OPTION_PRIORITY.md +0 -527
- package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
- package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
- package/docs/PERFORMANCE_ANALYSIS.md +0 -839
- package/docs/PERFORMANCE_COMPARISON.md +0 -388
- package/docs/noteExports.md +0 -148
- package/docs/security_improvement_for_V3.md +0 -421
- package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
- package/docs/template-engine/esempi-incrementali.js +0 -192
- package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
- package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
- package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
- package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
- package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
- package/docs/template-engine/examples/index-esempi.html +0 -181
- package/docs/template-engine/examples/index.html +0 -40
- package/docs/template-engine/examples/test.ejs +0 -64
- package/eslint.config.mjs +0 -17
- package/jest.config.js +0 -18
package/docs/ACTION_PLAN.md
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
# Piano d'Azione — koa-classic-server
|
|
2
|
-
|
|
3
|
-
> Documento di lavoro per il miglioramento progressivo del progetto.
|
|
4
|
-
> Ogni fase segue il ciclo: **Descrizione → Soluzioni proposte → Domande → Implementazione → Test → Avanzamento**
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Indice delle fasi
|
|
9
|
-
|
|
10
|
-
| # | Fase | Priorità | Stato |
|
|
11
|
-
|---|------|----------|-------|
|
|
12
|
-
| 1 | [File nascosti nel directory listing](#fase-1--file-nascosti-nel-directory-listing) | Alta | ⬜ Da fare |
|
|
13
|
-
| 2 | [Opzione glob per escludere file sensibili](#fase-2--opzione-glob-per-escludere-file-sensibili) | Alta | ⬜ Da fare |
|
|
14
|
-
| 3 | [Content-Security-Policy nell'HTML generato](#fase-3--content-security-policy-nellhtml-generato) | Media | ⬜ Da fare |
|
|
15
|
-
| 4 | [Aggiunta ESLint e standardizzazione `===`](#fase-4--aggiunta-eslint-e-standardizzazione-) | Media | ⬜ Da fare |
|
|
16
|
-
| 5 | [Range Requests HTTP 206](#fase-5--range-requests-http-206) | Media | ⬜ Da fare |
|
|
17
|
-
| 6 | [Gzip / Brotli compression](#fase-6--gzip--brotli-compression) | Media | ⬜ Da fare |
|
|
18
|
-
| 7 | [Traduzione commenti in inglese nei test](#fase-7--traduzione-commenti-in-inglese-nei-test) | Bassa | ⬜ Da fare |
|
|
19
|
-
| 8 | [Roadmap rimozione opzioni deprecate (v3.0.0)](#fase-8--roadmap-rimozione-opzioni-deprecate-v300) | Bassa | ⬜ Da fare |
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
> **Legenda stato:** ⬜ Da fare · 🔄 In corso · ✅ Completato · ⏸️ In pausa
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Processo standard per ogni fase
|
|
28
|
-
|
|
29
|
-
Per ogni fase si segue sempre questo ciclo:
|
|
30
|
-
|
|
31
|
-
1. **Descrizione** — Spiegazione del problema e del suo impatto
|
|
32
|
-
2. **Soluzioni proposte** — Almeno 2 alternative valutate con pro/contro
|
|
33
|
-
3. **Domande** — Se le informazioni disponibili sono < 90%, si chiedono chiarimenti prima di procedere
|
|
34
|
-
4. **Implementazione** — Modifica del codice sul branch `claude/project-review-EN6kt`
|
|
35
|
-
5. **Test** — Esecuzione della suite di test e verifica regressioni
|
|
36
|
-
6. **Avanzamento** — Aggiornamento dello stato in questo file e passaggio alla fase successiva
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Fase 1 — File nascosti nel directory listing
|
|
41
|
-
|
|
42
|
-
**Stato:** ⬜ Da fare
|
|
43
|
-
**Priorità:** Alta
|
|
44
|
-
**File coinvolti:** `index.cjs` (funzione `show_dir`)
|
|
45
|
-
|
|
46
|
-
### Descrizione del problema
|
|
47
|
-
|
|
48
|
-
Il directory listing mostra **tutti** i file e le cartelle presenti nella webroot, inclusi quelli che iniziano con `.` (dot files), come:
|
|
49
|
-
|
|
50
|
-
- `.env` — variabili d'ambiente con credenziali
|
|
51
|
-
- `.gitignore`, `.gitattributes` — metadati Git
|
|
52
|
-
- `.htpasswd` — password Apache
|
|
53
|
-
- `.DS_Store` — metadati macOS
|
|
54
|
-
- `.npmrc` — configurazioni npm con token
|
|
55
|
-
|
|
56
|
-
Server come Apache e Nginx nascondono questi file per default. Un file dimenticato nella webroot potrebbe esporre informazioni sensibili agli utenti del browser.
|
|
57
|
-
|
|
58
|
-
### Soluzioni proposte
|
|
59
|
-
|
|
60
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
61
|
-
|
|
62
|
-
### Domande
|
|
63
|
-
|
|
64
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
65
|
-
|
|
66
|
-
### Implementazione
|
|
67
|
-
|
|
68
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
69
|
-
|
|
70
|
-
### Test
|
|
71
|
-
|
|
72
|
-
*Da verificare dopo l'implementazione.*
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## Fase 2 — Opzione glob per escludere file sensibili
|
|
77
|
-
|
|
78
|
-
**Stato:** ⬜ Da fare
|
|
79
|
-
**Priorità:** Alta
|
|
80
|
-
**File coinvolti:** `index.cjs` (opzioni di configurazione + `show_dir`)
|
|
81
|
-
|
|
82
|
-
### Descrizione del problema
|
|
83
|
-
|
|
84
|
-
Non esiste un'opzione per escludere file o cartelle specifici dal serving e dal directory listing tramite pattern (glob o RegExp). Se un file come `config.json`, `secrets.yaml` o qualsiasi altro file sensibile si trova nella webroot, viene servito senza restrizioni.
|
|
85
|
-
|
|
86
|
-
Esempi di pattern utili:
|
|
87
|
-
- `*.env` — tutti i file .env
|
|
88
|
-
- `**/*.secret` — file con estensione .secret
|
|
89
|
-
- `private/**` — intera cartella private
|
|
90
|
-
|
|
91
|
-
### Soluzioni proposte
|
|
92
|
-
|
|
93
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
94
|
-
|
|
95
|
-
### Domande
|
|
96
|
-
|
|
97
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
98
|
-
|
|
99
|
-
### Implementazione
|
|
100
|
-
|
|
101
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
102
|
-
|
|
103
|
-
### Test
|
|
104
|
-
|
|
105
|
-
*Da verificare dopo l'implementazione.*
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## Fase 3 — Content-Security-Policy nell'HTML generato
|
|
110
|
-
|
|
111
|
-
**Stato:** ⬜ Da fare
|
|
112
|
-
**Priorità:** Media
|
|
113
|
-
**File coinvolti:** `index.cjs` (funzione `show_dir`)
|
|
114
|
-
|
|
115
|
-
### Descrizione del problema
|
|
116
|
-
|
|
117
|
-
Le pagine HTML generate dal directory listing non includono un header `Content-Security-Policy`. Senza CSP, il browser non ha indicazioni su quali risorse sono autorizzate, aumentando il rischio di attacchi XSS in caso di eventuali vulnerabilità future nel codice di generazione HTML.
|
|
118
|
-
|
|
119
|
-
Il progetto già implementa l'escape HTML (funzione `escapeHtml`), ma aggiungere CSP è un ulteriore livello di difesa in profondità.
|
|
120
|
-
|
|
121
|
-
### Soluzioni proposte
|
|
122
|
-
|
|
123
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
124
|
-
|
|
125
|
-
### Domande
|
|
126
|
-
|
|
127
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
128
|
-
|
|
129
|
-
### Implementazione
|
|
130
|
-
|
|
131
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
132
|
-
|
|
133
|
-
### Test
|
|
134
|
-
|
|
135
|
-
*Da verificare dopo l'implementazione.*
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Fase 4 — Aggiunta ESLint e standardizzazione `===`
|
|
140
|
-
|
|
141
|
-
**Stato:** ⬜ Da fare
|
|
142
|
-
**Priorità:** Media
|
|
143
|
-
**File coinvolti:** `index.cjs`, `package.json`, nuovi file di config
|
|
144
|
-
|
|
145
|
-
### Descrizione del problema
|
|
146
|
-
|
|
147
|
-
Il codice usa `==` (uguaglianza debole con coercizione di tipo) in circa 25 punti, documentati in `docs/CODE_REVIEW.md`. Anche se nel contesto attuale non causano bug, l'uso di `===` è la best practice JavaScript e previene errori sottili in futuro.
|
|
148
|
-
|
|
149
|
-
Inoltre il progetto non ha alcun linter o formatter configurato, il che rende difficile mantenere la coerenza stilistica nel tempo e nelle contribuzioni esterne.
|
|
150
|
-
|
|
151
|
-
### Soluzioni proposte
|
|
152
|
-
|
|
153
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
154
|
-
|
|
155
|
-
### Domande
|
|
156
|
-
|
|
157
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
158
|
-
|
|
159
|
-
### Implementazione
|
|
160
|
-
|
|
161
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
162
|
-
|
|
163
|
-
### Test
|
|
164
|
-
|
|
165
|
-
*Da verificare dopo l'implementazione.*
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## Fase 5 — Range Requests HTTP 206
|
|
170
|
-
|
|
171
|
-
**Stato:** ⬜ Da fare
|
|
172
|
-
**Priorità:** Media
|
|
173
|
-
**File coinvolti:** `index.cjs` (logica di file serving)
|
|
174
|
-
|
|
175
|
-
### Descrizione del problema
|
|
176
|
-
|
|
177
|
-
Il middleware non supporta l'header `Range` delle richieste HTTP. Questo significa che:
|
|
178
|
-
|
|
179
|
-
- File audio e video non possono essere riprodotti in streaming dai browser
|
|
180
|
-
- Download di file grandi non possono essere ripresi dopo interruzione
|
|
181
|
-
- Strumenti come `curl --range` non funzionano
|
|
182
|
-
|
|
183
|
-
Il supporto HTTP 206 (Partial Content) è lo standard per la distribuzione di contenuti multimediali e file di grandi dimensioni.
|
|
184
|
-
|
|
185
|
-
### Soluzioni proposte
|
|
186
|
-
|
|
187
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
188
|
-
|
|
189
|
-
### Domande
|
|
190
|
-
|
|
191
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
192
|
-
|
|
193
|
-
### Implementazione
|
|
194
|
-
|
|
195
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
196
|
-
|
|
197
|
-
### Test
|
|
198
|
-
|
|
199
|
-
*Da verificare dopo l'implementazione.*
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## Fase 6 — Gzip / Brotli compression
|
|
204
|
-
|
|
205
|
-
**Stato:** ⬜ Da fare
|
|
206
|
-
**Priorità:** Media
|
|
207
|
-
**File coinvolti:** `index.cjs`, `package.json`
|
|
208
|
-
|
|
209
|
-
### Descrizione del problema
|
|
210
|
-
|
|
211
|
-
Il middleware serve tutti i file senza compressione. Per file di testo (HTML, CSS, JS, JSON, SVG), la compressione può ridurre le dimensioni del 60-80%, con impatto diretto su:
|
|
212
|
-
|
|
213
|
-
- Velocità di caricamento per gli utenti
|
|
214
|
-
- Consumo di banda del server
|
|
215
|
-
- Score Lighthouse / Web Vitals
|
|
216
|
-
|
|
217
|
-
### Soluzioni proposte
|
|
218
|
-
|
|
219
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
220
|
-
|
|
221
|
-
### Domande
|
|
222
|
-
|
|
223
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
224
|
-
|
|
225
|
-
### Implementazione
|
|
226
|
-
|
|
227
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
228
|
-
|
|
229
|
-
### Test
|
|
230
|
-
|
|
231
|
-
*Da verificare dopo l'implementazione.*
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Fase 7 — Traduzione commenti in inglese nei test
|
|
236
|
-
|
|
237
|
-
**Stato:** ⬜ Da fare
|
|
238
|
-
**Priorità:** Bassa
|
|
239
|
-
**File coinvolti:** `__tests__/dt-unknown.test.js` e altri
|
|
240
|
-
|
|
241
|
-
### Descrizione del problema
|
|
242
|
-
|
|
243
|
-
Alcuni file di test contengono commenti in italiano, il che riduce l'accessibilità del codice per i contribuenti internazionali. Per un progetto open source pubblicato su npm, la lingua standard della codebase dovrebbe essere l'inglese.
|
|
244
|
-
|
|
245
|
-
### Soluzioni proposte
|
|
246
|
-
|
|
247
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
248
|
-
|
|
249
|
-
### Domande
|
|
250
|
-
|
|
251
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
252
|
-
|
|
253
|
-
### Implementazione
|
|
254
|
-
|
|
255
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
256
|
-
|
|
257
|
-
### Test
|
|
258
|
-
|
|
259
|
-
*Da verificare dopo l'implementazione.*
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Fase 8 — Roadmap rimozione opzioni deprecate (v3.0.0)
|
|
264
|
-
|
|
265
|
-
**Stato:** ⬜ Da fare
|
|
266
|
-
**Priorità:** Bassa
|
|
267
|
-
**File coinvolti:** `index.cjs`, `docs/CHANGELOG.md`, `README.md`
|
|
268
|
-
|
|
269
|
-
### Descrizione del problema
|
|
270
|
-
|
|
271
|
-
Le opzioni legacy `cacheMaxAge` ed `enableCaching` sono ancora supportate con deprecation warning ma non hanno una data di rimozione pianificata. Mantenerle a tempo indeterminato appesantisce il codice e può confondere i nuovi utenti che leggono la documentazione.
|
|
272
|
-
|
|
273
|
-
Una roadmap chiara verso `v3.0.0` con breaking changes definiti aiuta gli utenti a pianificare la migrazione.
|
|
274
|
-
|
|
275
|
-
### Soluzioni proposte
|
|
276
|
-
|
|
277
|
-
*Da definire nella sessione di lavoro dedicata a questa fase.*
|
|
278
|
-
|
|
279
|
-
### Domande
|
|
280
|
-
|
|
281
|
-
*Da porre prima dell'implementazione se necessario.*
|
|
282
|
-
|
|
283
|
-
### Implementazione
|
|
284
|
-
|
|
285
|
-
*Da eseguire dopo la scelta della soluzione.*
|
|
286
|
-
|
|
287
|
-
### Test
|
|
288
|
-
|
|
289
|
-
*Da verificare dopo l'implementazione.*
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
*Documento aggiornato: 2026-03-21*
|
package/docs/BENCHMARKS.md
DELETED
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
# Performance Benchmarks
|
|
2
|
-
|
|
3
|
-
This directory contains comprehensive performance benchmarks for `koa-classic-server`.
|
|
4
|
-
|
|
5
|
-
## Purpose
|
|
6
|
-
|
|
7
|
-
These benchmarks measure:
|
|
8
|
-
- **Response times** for different file sizes
|
|
9
|
-
- **Directory listing performance** for various sizes
|
|
10
|
-
- **Concurrent request handling**
|
|
11
|
-
- **Memory usage**
|
|
12
|
-
- **Throughput** (requests/second, MB/second)
|
|
13
|
-
|
|
14
|
-
## Quick Start
|
|
15
|
-
|
|
16
|
-
### 1. Setup Benchmark Data
|
|
17
|
-
|
|
18
|
-
First, create the test files and directories:
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npm run benchmark:setup
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
This creates:
|
|
25
|
-
- `benchmark-data/small-files/` - 100 files × 1KB
|
|
26
|
-
- `benchmark-data/medium-files/` - 50 files × 100KB
|
|
27
|
-
- `benchmark-data/large-files/` - 10 files × 1MB
|
|
28
|
-
- `benchmark-data/large-directory/` - 1,000 files for listing test
|
|
29
|
-
- `benchmark-data/very-large-directory/` - 10,000 files for stress test
|
|
30
|
-
- `benchmark-data/nested/` - 5 levels deep directory structure
|
|
31
|
-
|
|
32
|
-
Total: ~15 MB of test data
|
|
33
|
-
|
|
34
|
-
### 2. Run Jest Performance Tests
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm run test:performance
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
This runs comprehensive tests measuring:
|
|
41
|
-
- Individual file serving times
|
|
42
|
-
- Directory listing times
|
|
43
|
-
- Concurrent request handling
|
|
44
|
-
- 404 error handling
|
|
45
|
-
- Memory usage
|
|
46
|
-
|
|
47
|
-
**Save results:**
|
|
48
|
-
```bash
|
|
49
|
-
npm run test:performance > results-baseline-v1.2.0.txt
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### 3. Run HTTP Load Tests (autocannon)
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npm run benchmark
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
This performs realistic load testing with:
|
|
59
|
-
- 10 seconds per scenario
|
|
60
|
-
- 5-10 concurrent connections
|
|
61
|
-
- Measures requests/sec, latency, throughput
|
|
62
|
-
|
|
63
|
-
**Save results for comparison:**
|
|
64
|
-
```bash
|
|
65
|
-
npm run benchmark:save baseline-v1.2.0.json
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Workflow: Before/After Optimization
|
|
69
|
-
|
|
70
|
-
### Step 1: Baseline (BEFORE optimization)
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
# Setup test data
|
|
74
|
-
npm run benchmark:setup
|
|
75
|
-
|
|
76
|
-
# Run tests and save results
|
|
77
|
-
npm run test:performance > results-before.txt
|
|
78
|
-
npm run benchmark:save baseline-before.json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Step 2: Apply Optimizations
|
|
82
|
-
|
|
83
|
-
Make code changes to improve performance...
|
|
84
|
-
|
|
85
|
-
### Step 3: Compare (AFTER optimization)
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
# Run tests again
|
|
89
|
-
npm run test:performance > results-after.txt
|
|
90
|
-
npm run benchmark:save baseline-after.json --compare baseline-before.json
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Step 4: Analyze Differences
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
# Compare test results
|
|
97
|
-
diff results-before.txt results-after.txt
|
|
98
|
-
|
|
99
|
-
# Benchmark comparison is shown automatically
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Expected Improvements
|
|
103
|
-
|
|
104
|
-
After implementing the optimizations from `PERFORMANCE_ANALYSIS.md`:
|
|
105
|
-
|
|
106
|
-
| Metric | Before | After | Improvement |
|
|
107
|
-
|--------|--------|-------|-------------|
|
|
108
|
-
| Small file (1KB) | ~2.5ms | ~0.5ms | **80% faster** |
|
|
109
|
-
| Directory (1,000 files) | ~120ms | ~40ms | **67% faster** |
|
|
110
|
-
| Directory (10,000 files) | ~1,800ms | ~450ms | **75% faster** |
|
|
111
|
-
| Concurrent requests | Sequential | Parallel | **5-10x faster** |
|
|
112
|
-
| Memory (10k directory) | ~25MB | ~15MB | **40% less** |
|
|
113
|
-
|
|
114
|
-
With HTTP caching enabled:
|
|
115
|
-
| Metric | Before | After | Improvement |
|
|
116
|
-
|--------|--------|-------|-------------|
|
|
117
|
-
| Cached file | 2.5ms | 0.1ms | **96% faster** |
|
|
118
|
-
| Bandwidth | 100% | 5% | **95% reduction** |
|
|
119
|
-
|
|
120
|
-
## Understanding the Results
|
|
121
|
-
|
|
122
|
-
### Jest Performance Tests
|
|
123
|
-
|
|
124
|
-
Output includes:
|
|
125
|
-
- **Average time**: Mean across all iterations
|
|
126
|
-
- **Median time**: 50th percentile (less affected by outliers)
|
|
127
|
-
- **Min/Max time**: Range of values
|
|
128
|
-
- **Warnings**: Areas where optimizations will have big impact
|
|
129
|
-
|
|
130
|
-
Example output:
|
|
131
|
-
```
|
|
132
|
-
📊 Large Directory (1,000 files) Benchmark:
|
|
133
|
-
Average: 123.45ms
|
|
134
|
-
Median: 120.30ms
|
|
135
|
-
Min: 110.20ms
|
|
136
|
-
Max: 145.80ms
|
|
137
|
-
⚠️ WARNING: This will be MUCH faster after async optimization
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Autocannon Load Tests
|
|
141
|
-
|
|
142
|
-
Output includes:
|
|
143
|
-
- **Requests/sec**: How many requests the server can handle per second
|
|
144
|
-
- **Latency**: Response time (avg, p50, p99)
|
|
145
|
-
- **Throughput**: Data transferred per second (MB/sec)
|
|
146
|
-
|
|
147
|
-
Example output:
|
|
148
|
-
```
|
|
149
|
-
Scenario | Req/sec | Latency (avg) | Throughput
|
|
150
|
-
----------------------------------|---------|---------------|-------------
|
|
151
|
-
Small file (1KB) | 2500 | 4.00ms | 2.44 MB/s
|
|
152
|
-
Directory listing (1,000 files) | 80 | 125.00ms | 15.60 MB/s
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Higher **Requests/sec** = Better ✅
|
|
156
|
-
Lower **Latency** = Better ✅
|
|
157
|
-
Higher **Throughput** = Better ✅
|
|
158
|
-
|
|
159
|
-
## Interpreting Latency Percentiles
|
|
160
|
-
|
|
161
|
-
- **p50 (median)**: 50% of requests complete in this time
|
|
162
|
-
- **p75**: 75% of requests complete in this time
|
|
163
|
-
- **p90**: 90% of requests complete in this time
|
|
164
|
-
- **p99**: 99% of requests complete in this time
|
|
165
|
-
- **p999**: 99.9% of requests complete in this time
|
|
166
|
-
|
|
167
|
-
**Why p99 matters:**
|
|
168
|
-
- p50 might be 10ms, but p99 could be 100ms
|
|
169
|
-
- This means 1% of users experience 10× slower responses
|
|
170
|
-
- Optimizations should improve both average AND p99
|
|
171
|
-
|
|
172
|
-
## Memory Usage Tests
|
|
173
|
-
|
|
174
|
-
Memory tests show:
|
|
175
|
-
- **Heap used**: JavaScript objects, strings, arrays
|
|
176
|
-
- **External**: Buffers, native objects
|
|
177
|
-
- **Response size**: Size of HTML/data generated
|
|
178
|
-
|
|
179
|
-
**What to look for:**
|
|
180
|
-
- Large heap increase = memory leaks or inefficient allocation
|
|
181
|
-
- After optimization: should see 30-40% reduction
|
|
182
|
-
|
|
183
|
-
## Directory Structure
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
koa-classic-server/
|
|
187
|
-
├── benchmark-data/ # Test data (git-ignored, ~15MB)
|
|
188
|
-
│ ├── small-files/
|
|
189
|
-
│ ├── medium-files/
|
|
190
|
-
│ ├── large-files/
|
|
191
|
-
│ ├── large-directory/
|
|
192
|
-
│ └── very-large-directory/
|
|
193
|
-
├── scripts/
|
|
194
|
-
│ └── setup-benchmark.js # Creates test data
|
|
195
|
-
├── __tests__/
|
|
196
|
-
│ └── performance.test.js # Jest performance tests
|
|
197
|
-
├── benchmark.js # Autocannon load tests
|
|
198
|
-
└── BENCHMARKS.md # This file
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Troubleshooting
|
|
202
|
-
|
|
203
|
-
### "Benchmark data not found"
|
|
204
|
-
|
|
205
|
-
Run: `npm run benchmark:setup`
|
|
206
|
-
|
|
207
|
-
### Tests timeout
|
|
208
|
-
|
|
209
|
-
Increase Jest timeout in `performance.test.js`:
|
|
210
|
-
```javascript
|
|
211
|
-
test('...', async () => { ... }, 60000); // 60 seconds
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Out of memory
|
|
215
|
-
|
|
216
|
-
Reduce iterations or skip very-large-directory tests:
|
|
217
|
-
```javascript
|
|
218
|
-
test.skip('Very large directory...', async () => { ... });
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Inconsistent results
|
|
222
|
-
|
|
223
|
-
- Close other applications
|
|
224
|
-
- Run multiple times and average results
|
|
225
|
-
- Check system load: `top` or `htop`
|
|
226
|
-
- Disable CPU throttling
|
|
227
|
-
|
|
228
|
-
## Best Practices
|
|
229
|
-
|
|
230
|
-
1. **Run on idle system**: Close browsers, apps
|
|
231
|
-
2. **Run multiple times**: Results vary, average 3+ runs
|
|
232
|
-
3. **Same environment**: Use same machine for before/after
|
|
233
|
-
4. **Document environment**: Note CPU, RAM, Node version
|
|
234
|
-
5. **Save results**: Use `> file.txt` to save for comparison
|
|
235
|
-
|
|
236
|
-
## Example: Complete Before/After Test
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
# === BEFORE OPTIMIZATION ===
|
|
240
|
-
|
|
241
|
-
# Setup
|
|
242
|
-
npm run benchmark:setup
|
|
243
|
-
|
|
244
|
-
# Jest tests
|
|
245
|
-
npm run test:performance > results-v1.2.0-before.txt
|
|
246
|
-
|
|
247
|
-
# Load tests
|
|
248
|
-
npm run benchmark:save baseline-v1.2.0.json
|
|
249
|
-
|
|
250
|
-
# === APPLY OPTIMIZATIONS ===
|
|
251
|
-
# Edit index.cjs...
|
|
252
|
-
|
|
253
|
-
# === AFTER OPTIMIZATION ===
|
|
254
|
-
|
|
255
|
-
# Jest tests
|
|
256
|
-
npm run test:performance > results-v1.3.0-after.txt
|
|
257
|
-
|
|
258
|
-
# Load tests with comparison
|
|
259
|
-
node benchmark.js --save baseline-v1.3.0.json --compare baseline-v1.2.0.json
|
|
260
|
-
|
|
261
|
-
# Review differences
|
|
262
|
-
diff results-v1.2.0-before.txt results-v1.3.0-after.txt
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## Environment Information
|
|
266
|
-
|
|
267
|
-
When reporting results, include:
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
node --version
|
|
271
|
-
npm --version
|
|
272
|
-
cat /proc/cpuinfo | grep "model name" | head -n 1
|
|
273
|
-
free -h
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
Example:
|
|
277
|
-
```
|
|
278
|
-
Node.js: v20.10.0
|
|
279
|
-
npm: 10.2.3
|
|
280
|
-
CPU: Intel(R) Core(TM) i7-9750H @ 2.60GHz
|
|
281
|
-
RAM: 16GB
|
|
282
|
-
OS: Ubuntu 22.04 LTS
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
## Next Steps
|
|
286
|
-
|
|
287
|
-
After running baseline benchmarks:
|
|
288
|
-
|
|
289
|
-
1. Review `PERFORMANCE_ANALYSIS.md` for optimization recommendations
|
|
290
|
-
2. Review `OPTIMIZATION_HTTP_CACHING.md` for HTTP caching details
|
|
291
|
-
3. Implement Priority 1 optimizations:
|
|
292
|
-
- Convert sync operations to async
|
|
293
|
-
- Fix string concatenation in `show_dir()`
|
|
294
|
-
- Add HTTP caching headers
|
|
295
|
-
4. Re-run benchmarks to measure improvements
|
|
296
|
-
5. Update to v1.3.0 "Performance Edition"
|
|
297
|
-
|
|
298
|
-
## Contributing
|
|
299
|
-
|
|
300
|
-
When submitting performance improvements:
|
|
301
|
-
|
|
302
|
-
1. Run baseline benchmarks BEFORE changes
|
|
303
|
-
2. Apply your optimization
|
|
304
|
-
3. Run benchmarks AFTER changes
|
|
305
|
-
4. Include both results in PR
|
|
306
|
-
5. Document the optimization approach
|
|
307
|
-
|
|
308
|
-
## Resources
|
|
309
|
-
|
|
310
|
-
- [autocannon documentation](https://github.com/mcollina/autocannon)
|
|
311
|
-
- [Jest performance testing](https://jestjs.io/docs/timer-mocks)
|
|
312
|
-
- [Node.js performance best practices](https://nodejs.org/en/docs/guides/simple-profiling/)
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
**Last updated**: 2025-11-18
|
|
317
|
-
**Version**: 1.2.0 (baseline)
|