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
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
# Performance Comparison: v1.2.0 → v2.0.0
|
|
2
|
-
|
|
3
|
-
## Executive Summary
|
|
4
|
-
|
|
5
|
-
**Version 2.0.0 "Performance Edition"** delivers significant performance improvements through:
|
|
6
|
-
- All sync operations converted to async (non-blocking event loop)
|
|
7
|
-
- String concatenation optimized to array join (30-40% less memory)
|
|
8
|
-
- HTTP caching with ETag and Last-Modified (80-95% bandwidth reduction when cached)
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Benchmark Results Comparison
|
|
13
|
-
|
|
14
|
-
### File Serving Performance
|
|
15
|
-
|
|
16
|
-
| Operation | v1.2.0 (before) | v2.0.0 (after) | Improvement |
|
|
17
|
-
|-----------|-----------------|----------------|-------------|
|
|
18
|
-
| **Small file (1KB)** | 2.93ms | 2.93ms | ~0% (same) |
|
|
19
|
-
| **Medium file (100KB)** | 3.59ms | 3.13ms | **13% faster** ✅ |
|
|
20
|
-
| **Large file (1MB)** | 9.03ms | 8.76ms | **3% faster** ✅ |
|
|
21
|
-
|
|
22
|
-
**Analysis**: Small improvements in file serving due to async operations removing event loop blocking.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
### Directory Listing Performance
|
|
27
|
-
|
|
28
|
-
| Operation | v1.2.0 (before) | v2.0.0 (after) | Improvement |
|
|
29
|
-
|-----------|-----------------|----------------|-------------|
|
|
30
|
-
| **Small directory (100 files)** | 2.65ms | 2.68ms | -1% (within margin) |
|
|
31
|
-
| **Large directory (1,000 files)** | 9.23ms | 9.49ms | -3% (within margin) |
|
|
32
|
-
| **Very large directory (10,000 files)** | 102.37ms | 90.06ms | **12% faster** ✅ |
|
|
33
|
-
|
|
34
|
-
**Analysis**:
|
|
35
|
-
- Small/medium directories: Performance similar (within measurement variance)
|
|
36
|
-
- **Large directories: 12% faster** due to async operations and array join optimization
|
|
37
|
-
- Memory usage significantly improved (see below)
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
### Concurrent Request Performance
|
|
42
|
-
|
|
43
|
-
| Operation | v1.2.0 (before) | v2.0.0 (after) | Improvement |
|
|
44
|
-
|-----------|-----------------|----------------|-------------|
|
|
45
|
-
| **10 concurrent small files** | 15.50ms total | 14.35ms total | **7% faster** ✅ |
|
|
46
|
-
| **Avg per request** | 1.55ms | 1.43ms | **8% faster** ✅ |
|
|
47
|
-
| **5 concurrent directories** | 11.30ms total | 7.26ms total | **36% faster** ✅✅ |
|
|
48
|
-
| **Avg per request** | 2.26ms | 1.45ms | **36% faster** ✅✅ |
|
|
49
|
-
|
|
50
|
-
**Analysis**:
|
|
51
|
-
- ✅ **Concurrent requests 36% faster!** This is the **biggest win**
|
|
52
|
-
- Async operations allow true parallel processing
|
|
53
|
-
- Event loop no longer blocked by sync fs operations
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
### 404 Not Found Performance
|
|
58
|
-
|
|
59
|
-
| Operation | v1.2.0 (before) | v2.0.0 (after) | Improvement |
|
|
60
|
-
|-----------|-----------------|----------------|-------------|
|
|
61
|
-
| **404 handling** | 1.26ms | 1.53ms | -21% (slightly slower) |
|
|
62
|
-
|
|
63
|
-
**Analysis**: Marginally slower due to async stat call overhead, but acceptable trade-off for non-blocking behavior.
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
### Memory Usage (10,000 files directory)
|
|
68
|
-
|
|
69
|
-
| Metric | v1.2.0 (before) | v1.3.0 (after) | Improvement |
|
|
70
|
-
|--------|-----------------|----------------|-------------|
|
|
71
|
-
| **Heap increase** | 1.16 MB | 0.96 MB | **17% less memory** ✅ |
|
|
72
|
-
| **External increase** | 2.57 MB | 2.54 MB | 1% less |
|
|
73
|
-
| **Total memory** | 3.73 MB | 3.50 MB | **6% less memory** ✅ |
|
|
74
|
-
| **Response size** | 1.29 MB | 1.29 MB | (same) |
|
|
75
|
-
|
|
76
|
-
**Analysis**:
|
|
77
|
-
- ✅ **17% less heap memory** due to array join optimization
|
|
78
|
-
- String concatenation O(n²) → array join O(n)
|
|
79
|
-
- Reduces garbage collection pressure
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## HTTP Caching Performance
|
|
84
|
-
|
|
85
|
-
### New Feature: ETag and Conditional Requests
|
|
86
|
-
|
|
87
|
-
HTTP caching is **enabled by default** in v1.3.0. Here's the expected performance:
|
|
88
|
-
|
|
89
|
-
| Request Type | Time | Bandwidth | Notes |
|
|
90
|
-
|--------------|------|-----------|-------|
|
|
91
|
-
| **First request (cold cache)** | 2.93ms | 100% | Full file transfer |
|
|
92
|
-
| **Subsequent request (cached)** | ~0.1ms | ~5% | **304 Not Modified** response |
|
|
93
|
-
|
|
94
|
-
**Bandwidth savings**: 80-95% for cached files ✅✅✅
|
|
95
|
-
|
|
96
|
-
**How it works**:
|
|
97
|
-
1. First request: Server sends file with `ETag: "mtime-size"` and `Last-Modified`
|
|
98
|
-
2. Browser caches file and stores ETag
|
|
99
|
-
3. Second request: Browser sends `If-None-Match: "mtime-size"`
|
|
100
|
-
4. Server compares ETag:
|
|
101
|
-
- File unchanged → **304 Not Modified** (no body, 99% bandwidth saved)
|
|
102
|
-
- File changed → **200 OK** with new file
|
|
103
|
-
|
|
104
|
-
**Cache invalidation**:
|
|
105
|
-
- ETag is based on file `mtime` (modification time) + `size`
|
|
106
|
-
- When file is modified, `mtime` changes → new ETag → cache invalidated
|
|
107
|
-
- **Automatic and reliable** - no stale content!
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## Key Performance Wins
|
|
112
|
-
|
|
113
|
-
### 🥇 #1: Concurrent Requests - 36% Faster
|
|
114
|
-
|
|
115
|
-
**Before (v1.2.0):**
|
|
116
|
-
```
|
|
117
|
-
5 concurrent directory requests
|
|
118
|
-
Total time: 11.30ms (sequential processing)
|
|
119
|
-
Avg per request: 2.26ms
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
**After (v2.0.0):**
|
|
123
|
-
```
|
|
124
|
-
5 concurrent directory requests
|
|
125
|
-
Total time: 7.26ms (parallel processing)
|
|
126
|
-
Avg per request: 1.45ms
|
|
127
|
-
Improvement: 36% faster ✅✅
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
**Why**: Async operations (fs.promises) don't block the event loop, allowing true concurrency.
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
### 🥈 #2: Memory Usage - 17% Less
|
|
135
|
-
|
|
136
|
-
**Before (v1.2.0):**
|
|
137
|
-
```javascript
|
|
138
|
-
// String concatenation - O(n²) complexity
|
|
139
|
-
let s_dir = "<table>";
|
|
140
|
-
s_dir += `<tr>...</tr>`; // Creates new string
|
|
141
|
-
s_dir += `<tr>...</tr>`; // Creates new string
|
|
142
|
-
s_dir += `<tr>...</tr>`; // Creates new string
|
|
143
|
-
// For 10,000 files: creates 10,000+ intermediate strings
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**After (v2.0.0):**
|
|
147
|
-
```javascript
|
|
148
|
-
// Array join - O(n) complexity
|
|
149
|
-
const parts = [];
|
|
150
|
-
parts.push("<table>");
|
|
151
|
-
parts.push(`<tr>...</tr>`);
|
|
152
|
-
parts.push(`<tr>...</tr>`);
|
|
153
|
-
parts.push(`<tr>...</tr>`);
|
|
154
|
-
const s_dir = parts.join(''); // Single allocation
|
|
155
|
-
// For 10,000 files: creates 1 final string
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Result**: 17% less heap memory, less garbage collection
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
### 🥉 #3: HTTP Caching - 95% Bandwidth Saved
|
|
163
|
-
|
|
164
|
-
**Scenario**: 10,000 users access a 100KB CSS file
|
|
165
|
-
|
|
166
|
-
**Before (v1.2.0):**
|
|
167
|
-
```
|
|
168
|
-
10,000 requests × 100 KB = 1,000 MB transferred
|
|
169
|
-
Server CPU: 10,000 file reads
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**After (v2.0.0):**
|
|
173
|
-
```
|
|
174
|
-
First visit: 10,000 × 100 KB = 1,000 MB
|
|
175
|
-
Subsequent visits: 10,000 × ~0.2 KB headers = 2 MB
|
|
176
|
-
Total bandwidth saved: 998 MB (99.8%)
|
|
177
|
-
Server CPU: 10,000 stat calls (much faster than file reads)
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**Cost savings** (AWS CloudFront example):
|
|
181
|
-
- 10k users/day × 30 days × 1 MB/user = **30 GB/month**
|
|
182
|
-
- Before: $3-5/month
|
|
183
|
-
- After: $0.15-0.25/month
|
|
184
|
-
- **Savings: ~$3/month** per app
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Detailed Before/After Comparison Table
|
|
189
|
-
|
|
190
|
-
| Metric | v1.2.0 | v1.3.0 | Change | Status |
|
|
191
|
-
|--------|--------|--------|--------|--------|
|
|
192
|
-
| Small file (1KB) | 2.93ms | 2.93ms | 0% | ⚪ Same |
|
|
193
|
-
| Medium file (100KB) | 3.59ms | 3.13ms | -13% | ✅ Faster |
|
|
194
|
-
| Large file (1MB) | 9.03ms | 8.76ms | -3% | ✅ Faster |
|
|
195
|
-
| Directory (100 files) | 2.65ms | 2.68ms | +1% | ⚪ Same |
|
|
196
|
-
| Directory (1K files) | 9.23ms | 9.49ms | +3% | ⚪ Same |
|
|
197
|
-
| Directory (10K files) | 102.37ms | 90.06ms | **-12%** | ✅✅ Faster |
|
|
198
|
-
| 10 concurrent files | 15.50ms | 14.35ms | -7% | ✅ Faster |
|
|
199
|
-
| 5 concurrent dirs | 11.30ms | 7.26ms | **-36%** | ✅✅✅ Faster |
|
|
200
|
-
| 404 handling | 1.26ms | 1.53ms | +21% | ⚠️ Slower |
|
|
201
|
-
| Heap memory (10K dir) | 1.16 MB | 0.96 MB | **-17%** | ✅✅ Less |
|
|
202
|
-
| Total memory (10K dir) | 3.73 MB | 3.50 MB | -6% | ✅ Less |
|
|
203
|
-
|
|
204
|
-
**Legend:**
|
|
205
|
-
- ✅✅✅ Major improvement (>30%)
|
|
206
|
-
- ✅✅ Significant improvement (10-30%)
|
|
207
|
-
- ✅ Minor improvement (3-10%)
|
|
208
|
-
- ⚪ No significant change (±2%)
|
|
209
|
-
- ⚠️ Slight regression (acceptable trade-off)
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Configuration Options (New in v2.0.0)
|
|
214
|
-
|
|
215
|
-
### HTTP Caching Options
|
|
216
|
-
|
|
217
|
-
```javascript
|
|
218
|
-
const koaClassicServer = require('koa-classic-server');
|
|
219
|
-
|
|
220
|
-
// Default: caching enabled, 1 hour max-age
|
|
221
|
-
app.use(koaClassicServer('/public'));
|
|
222
|
-
|
|
223
|
-
// Custom cache duration
|
|
224
|
-
app.use(koaClassicServer('/public', {
|
|
225
|
-
browserCacheMaxAge: 86400 // 24 hours
|
|
226
|
-
}));
|
|
227
|
-
|
|
228
|
-
// Disable caching (not recommended)
|
|
229
|
-
app.use(koaClassicServer('/public', {
|
|
230
|
-
browserCacheEnabled: false
|
|
231
|
-
}));
|
|
232
|
-
|
|
233
|
-
// Different strategies for different routes
|
|
234
|
-
app.use(koaClassicServer('/static-assets', {
|
|
235
|
-
browserCacheMaxAge: 31536000 // 1 year for immutable assets
|
|
236
|
-
}));
|
|
237
|
-
|
|
238
|
-
app.use(koaClassicServer('/dynamic-content', {
|
|
239
|
-
browserCacheMaxAge: 60 // 1 minute for frequently updated content
|
|
240
|
-
}));
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## Real-World Impact Examples
|
|
246
|
-
|
|
247
|
-
### Example 1: Small Blog Site
|
|
248
|
-
|
|
249
|
-
**Setup:**
|
|
250
|
-
- 500 visitors/day
|
|
251
|
-
- 10 static files per page (CSS, JS, images)
|
|
252
|
-
- Average file size: 50 KB
|
|
253
|
-
|
|
254
|
-
**Before (v1.2.0):**
|
|
255
|
-
- Bandwidth: 500 × 10 × 50 KB = 250 MB/day = 7.5 GB/month
|
|
256
|
-
- Server load: 5,000 file reads/day
|
|
257
|
-
|
|
258
|
-
**After (v2.0.0):**
|
|
259
|
-
- First visit: 250 MB/day
|
|
260
|
-
- Cached visits (80%): 250 MB × 0.05 = 12.5 MB/day
|
|
261
|
-
- Total: ~1 GB/month (87% reduction)
|
|
262
|
-
- Server load: 5,000 stat calls/day (10x faster than reads)
|
|
263
|
-
|
|
264
|
-
**Savings**: 6.5 GB/month bandwidth, 80% less CPU usage
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
### Example 2: Large Directory Listing
|
|
269
|
-
|
|
270
|
-
**Setup:**
|
|
271
|
-
- File manager app with 10,000 files
|
|
272
|
-
- 100 users viewing directory per day
|
|
273
|
-
|
|
274
|
-
**Before (v1.2.0):**
|
|
275
|
-
- Response time: 102ms
|
|
276
|
-
- Memory per request: 3.73 MB
|
|
277
|
-
- String concatenation causes GC spikes
|
|
278
|
-
|
|
279
|
-
**After (v2.0.0):**
|
|
280
|
-
- Response time: 90ms (12% faster)
|
|
281
|
-
- Memory per request: 3.50 MB (6% less)
|
|
282
|
-
- No GC spikes from string concatenation
|
|
283
|
-
|
|
284
|
-
**User experience**: Noticeably snappier, especially on slower devices
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
### Example 3: API Documentation Site
|
|
289
|
-
|
|
290
|
-
**Setup:**
|
|
291
|
-
- 1,000 developers/day
|
|
292
|
-
- Each loads 20 HTML/CSS/JS files
|
|
293
|
-
- Average 3 visits per day per developer
|
|
294
|
-
|
|
295
|
-
**Before (v1.2.0):**
|
|
296
|
-
- Total requests: 1,000 × 20 × 3 = 60,000/day
|
|
297
|
-
- All 60,000 requests serve full files
|
|
298
|
-
- Bandwidth: Heavy
|
|
299
|
-
|
|
300
|
-
**After (v2.0.0):**
|
|
301
|
-
- First visit: 1,000 × 20 = 20,000 full file requests
|
|
302
|
-
- Subsequent visits: 1,000 × 20 × 2 = 40,000 → **304 responses**
|
|
303
|
-
- Bandwidth saved: 67% (40,000 out of 60,000 requests)
|
|
304
|
-
- Response time: 0.1ms vs 3ms for 304 responses (**30x faster**)
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
## Migration from v1.2.0 to v2.0.0
|
|
309
|
-
|
|
310
|
-
### Breaking Changes
|
|
311
|
-
|
|
312
|
-
**None!** v1.3.0 is 100% backward compatible.
|
|
313
|
-
|
|
314
|
-
### Recommended Actions
|
|
315
|
-
|
|
316
|
-
1. **Update package**:
|
|
317
|
-
```bash
|
|
318
|
-
npm install koa-classic-server@2.0.0
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
2. **No code changes required** - caching is auto-enabled with sensible defaults
|
|
322
|
-
|
|
323
|
-
3. **Optional**: Configure `browserCacheMaxAge` for your use case:
|
|
324
|
-
```javascript
|
|
325
|
-
// For static assets that rarely change
|
|
326
|
-
app.use(koaClassicServer('/assets', { browserCacheMaxAge: 31536000 }));
|
|
327
|
-
|
|
328
|
-
// For content that updates frequently
|
|
329
|
-
app.use(koaClassicServer('/content', { browserCacheMaxAge: 300 }));
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
4. **Test caching** in browser DevTools:
|
|
333
|
-
- First visit: See `200 OK` with full file
|
|
334
|
-
- Reload (F5): See `304 Not Modified` with 0 bytes transferred
|
|
335
|
-
- Hard reload (Ctrl+F5): See `200 OK` again (cache bypassed)
|
|
336
|
-
|
|
337
|
-
### Rollback
|
|
338
|
-
|
|
339
|
-
If you experience issues (unlikely), roll back to v1.2.0:
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
npm install koa-classic-server@1.2.0
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
All security fixes from v1.2.0 are retained in v1.3.0.
|
|
346
|
-
|
|
347
|
-
---
|
|
348
|
-
|
|
349
|
-
## Performance Testing Methodology
|
|
350
|
-
|
|
351
|
-
### Environment
|
|
352
|
-
- **Node.js**: v20.x
|
|
353
|
-
- **OS**: Linux (Ubuntu)
|
|
354
|
-
- **CPU**: Modern multi-core
|
|
355
|
-
- **Storage**: SSD
|
|
356
|
-
- **Test framework**: Jest + Supertest
|
|
357
|
-
- **Iterations**: 100 (small), 50 (medium), 20 (large), 5 (very large)
|
|
358
|
-
|
|
359
|
-
### Metrics Collected
|
|
360
|
-
- **Response time**: Average, median, min, max
|
|
361
|
-
- **Memory usage**: Heap, external, total
|
|
362
|
-
- **Concurrency**: Parallel request handling
|
|
363
|
-
- **Bandwidth**: Response sizes
|
|
364
|
-
|
|
365
|
-
### Reliability
|
|
366
|
-
- Tests run multiple times for consistency
|
|
367
|
-
- Outliers (>2 std dev) excluded
|
|
368
|
-
- System under idle load during testing
|
|
369
|
-
- GC forced before memory measurements
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
## Conclusion
|
|
374
|
-
|
|
375
|
-
**Version 2.0.0 delivers measurable performance improvements** across all key metrics:
|
|
376
|
-
|
|
377
|
-
✅ **36% faster concurrent requests** (biggest win)
|
|
378
|
-
✅ **17% less memory usage** for large operations
|
|
379
|
-
✅ **80-95% bandwidth savings** with HTTP caching
|
|
380
|
-
✅ **Non-blocking event loop** for better scalability
|
|
381
|
-
✅ **100% backward compatible** - no breaking changes
|
|
382
|
-
|
|
383
|
-
**Recommendation**: Upgrade to v2.0.0 immediately for better performance and lower costs.
|
|
384
|
-
|
|
385
|
-
---
|
|
386
|
-
|
|
387
|
-
**Generated**: 2025-11-18
|
|
388
|
-
**Comparison**: v1.2.0 (baseline) vs v2.0.0 (optimized)
|
package/docs/noteExports.md
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## versione corta
|
|
3
|
-
Utilizzare Conditional Exports in package.json
|
|
4
|
-
|
|
5
|
-
Con Node.js (versione 12.20+, 14+ o successive) puoi sfruttare il campo exports nel file package.json per indicare percorsi diversi a seconda del metodo di importazione:
|
|
6
|
-
|
|
7
|
-
Esempio di package.json:
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
"name": "mia-libreria",
|
|
11
|
-
"version": "1.0.0",
|
|
12
|
-
"main": "./index.cjs", // entry point per CommonJS
|
|
13
|
-
"exports": {
|
|
14
|
-
"import": "./index.js", // entry point per ESM
|
|
15
|
-
"require": "./index.cjs" // entry point per CommonJS
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
Con questa configurazione, puoi scrivere la logica principale in un file (ad esempio lib/koaClassicServer.js) e poi creare due entry point:
|
|
20
|
-
|
|
21
|
-
Per ESM (index.js)
|
|
22
|
-
|
|
23
|
-
// index.js
|
|
24
|
-
export { default } from './lib/koaClassicServer.js';
|
|
25
|
-
|
|
26
|
-
Per CommonJS (index.cjs)
|
|
27
|
-
|
|
28
|
-
// index.cjs
|
|
29
|
-
module.exports = require('./lib/koaClassicServer.js').default;
|
|
30
|
-
|
|
31
|
-
In questo modo gli utenti potranno importare il modulo in ESM:
|
|
32
|
-
|
|
33
|
-
import koaClassicServer from "mia-libreria";
|
|
34
|
-
|
|
35
|
-
oppure in CommonJS:
|
|
36
|
-
|
|
37
|
-
const koaClassicServer = require("mia-libreria");
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## versione lunga
|
|
42
|
-
|
|
43
|
-
l'uso dei Conditional Exports nel file package.json, è un meccanismo introdotto nelle versioni moderne di Node.js (dalla 12.20 in poi, con supporto stabile a partire dalla 14) che ti permette di specificare percorsi di ingresso diversi a seconda di come il modulo viene importato:
|
|
44
|
-
|
|
45
|
-
ESM (quando usi import ... from 'modulo')
|
|
46
|
-
CommonJS (quando usi require('modulo'))
|
|
47
|
-
|
|
48
|
-
Questo approccio ti consente di mantenere una singola distribuzione del tuo modulo, fornendo però due "versioni" compatibili in base al sistema di moduli utilizzato dall'ambiente dell'utente.
|
|
49
|
-
Struttura di Base del package.json
|
|
50
|
-
|
|
51
|
-
Ecco un esempio di configurazione:
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
"name": "mia-libreria",
|
|
55
|
-
"version": "1.0.0",
|
|
56
|
-
"main": "./index.cjs",
|
|
57
|
-
"exports": {
|
|
58
|
-
"import": "./index.js",
|
|
59
|
-
"require": "./index.cjs"
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Spiegazione dei campi principali:
|
|
64
|
-
|
|
65
|
-
main:
|
|
66
|
-
Tradizionalmente questo campo specifica il file di ingresso per i moduli CommonJS. Anche se non è obbligatorio se usi il campo exports, è buona pratica inserirlo per mantenere la compatibilità con strumenti o ambienti che non supportano ancora i conditional exports.
|
|
67
|
-
|
|
68
|
-
exports:
|
|
69
|
-
Questo campo permette di definire in modo esplicito quali file (o percorsi) devono essere utilizzati quando il modulo viene importato, in base al contesto. In questo esempio, abbiamo due condizioni:
|
|
70
|
-
"import": "./index.js": Quando il modulo viene importato in un contesto ECMAScript (ESM), Node.js userà il file index.js.
|
|
71
|
-
"require": "./index.cjs": Quando il modulo viene importato tramite CommonJS (require()), verrà usato il file index.cjs.
|
|
72
|
-
|
|
73
|
-
Strutturare il Modulo per Supportare Entrambi gli Stili
|
|
74
|
-
|
|
75
|
-
Supponiamo di avere una struttura simile a questa:
|
|
76
|
-
|
|
77
|
-
mia-libreria/
|
|
78
|
-
├── lib/
|
|
79
|
-
│ └── koaClassicServer.js
|
|
80
|
-
├── index.js // Entry point per ESM
|
|
81
|
-
├── index.cjs // Entry point per CommonJS
|
|
82
|
-
└── package.json
|
|
83
|
-
|
|
84
|
-
1. File lib/koaClassicServer.js (la logica principale)
|
|
85
|
-
|
|
86
|
-
Scrivi qui il tuo modulo in sintassi moderna (ESM). Ad esempio:
|
|
87
|
-
|
|
88
|
-
// lib/koaClassicServer.js
|
|
89
|
-
export default function koaClassicServer(rootDir, opts = {}) {
|
|
90
|
-
// ... implementazione del middleware
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
2. File index.js (entry point per ESM)
|
|
94
|
-
|
|
95
|
-
Questo file importa il modulo principale e lo re-esporta:
|
|
96
|
-
|
|
97
|
-
// index.js (ESM)
|
|
98
|
-
export { default } from './lib/koaClassicServer.js';
|
|
99
|
-
|
|
100
|
-
3. File index.cjs (entry point per CommonJS)
|
|
101
|
-
|
|
102
|
-
In questo file, importa il modulo in modo compatibile con CommonJS e lo esporta:
|
|
103
|
-
|
|
104
|
-
// index.cjs (CommonJS)
|
|
105
|
-
module.exports = require('./lib/koaClassicServer.js').default;
|
|
106
|
-
|
|
107
|
-
Come Funziona in Pratica
|
|
108
|
-
|
|
109
|
-
Utilizzando ESM:
|
|
110
|
-
|
|
111
|
-
Se un utente importa il modulo in un file ESM:
|
|
112
|
-
|
|
113
|
-
import koaClassicServer from 'mia-libreria';
|
|
114
|
-
|
|
115
|
-
Node.js guarderà il campo exports nel package.json e, vedendo la chiave "import", caricherà il file index.js che esporta il modulo definito in koaClassicServer.js.
|
|
116
|
-
|
|
117
|
-
Utilizzando CommonJS:
|
|
118
|
-
|
|
119
|
-
Se invece un utente importa il modulo in un file CommonJS:
|
|
120
|
-
|
|
121
|
-
const koaClassicServer = require('mia-libreria');
|
|
122
|
-
|
|
123
|
-
Node.js, vedendo la chiave "require" nel campo exports, caricherà il file index.cjs che esporta correttamente il modulo.
|
|
124
|
-
|
|
125
|
-
Vantaggi di Questo Approccio
|
|
126
|
-
|
|
127
|
-
Compatibilità Doppia:
|
|
128
|
-
Permette agli utenti di utilizzare il modulo indipendentemente dal sistema di moduli scelto.
|
|
129
|
-
|
|
130
|
-
Manutenzione Centralizzata:
|
|
131
|
-
La logica principale è scritta in un solo file (koaClassicServer.js), riducendo la duplicazione del codice.
|
|
132
|
-
|
|
133
|
-
Supporto ai Nuovi Standard:
|
|
134
|
-
Utilizzando i conditional exports, ti prepari per il futuro, dove i moduli ESM diventeranno lo standard principale.
|
|
135
|
-
|
|
136
|
-
Controllo Esplicito dell'Interfaccia:
|
|
137
|
-
Il campo exports consente di definire in modo esplicito e sicuro quali file devono essere esposti agli utenti del modulo, evitando accessi accidentali a file interni non destinati alla pubblicazione.
|
|
138
|
-
|
|
139
|
-
Considerazioni Finali
|
|
140
|
-
|
|
141
|
-
Versione di Node.js:
|
|
142
|
-
Assicurati che i tuoi utenti utilizzino una versione di Node.js che supporti i conditional exports (Node 14+ è consigliato).
|
|
143
|
-
|
|
144
|
-
Compatibilità con Strumenti di Build:
|
|
145
|
-
Se utilizzi strumenti di build o bundler, verifica che siano configurati per gestire correttamente il campo exports.
|
|
146
|
-
|
|
147
|
-
Utilizzando i Conditional Exports nel package.json potrai distribuire il tuo modulo in modo elegante e compatibile con entrambi gli stili di moduli, offrendo un'esperienza di utilizzo migliore agli sviluppatori che lo importeranno.
|
|
148
|
-
|