ultimate-express 1.2.7 → 1.2.9
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 +16 -15
- package/package.json +1 -1
- package/src/response.js +15 -24
package/README.md
CHANGED
|
@@ -34,23 +34,23 @@ Tested using [wrk](https://github.com/wg/wrk) (`-d 60 -t 1 -c 200`). Etag was di
|
|
|
34
34
|
| routers/nested-routers (/abccc/nested/ddd) | 10.25k | 50.98k | 1.83 MB/sec | 7.98 MB/sec | **4.97X** |
|
|
35
35
|
| middlewares/express-static (/static/index.js) | 7.52k | 31.08k | 6.92 MB/sec | 26.48 MB/sec | **4.13X** |
|
|
36
36
|
| engines/ejs (/test) | 5.92k | 41.64k | 2.40 MB/sec | 16.55 MB/sec | **7.03X** |
|
|
37
|
-
| middlewares/body-urlencoded (/abc) |
|
|
37
|
+
| middlewares/body-urlencoded (/abc) | 8.01k | 35.10k | 1.66 MB/sec | 7.02 MB/sec | **4.38X** |
|
|
38
38
|
|
|
39
39
|
### Performance against other frameworks
|
|
40
40
|
|
|
41
41
|
Tested using [bun-http-framework-benchmark](https://github.com/dimdenGD/bun-http-framework-benchmark). This table only includes Node.js results.
|
|
42
42
|
For full table with other runtimes, check [here](https://github.com/dimdenGD/bun-http-framework-benchmark?tab=readme-ov-file#results).
|
|
43
43
|
|
|
44
|
-
| Framework
|
|
45
|
-
|
|
|
46
|
-
| uws
|
|
47
|
-
| hyper-express
|
|
44
|
+
| Framework | Average | Ping | Query | Body |
|
|
45
|
+
| -------------------- | ------------- | ------------- | ------------- | ------------- |
|
|
46
|
+
| uws | 94,296.49 | 108,551.92 | 104,756.22 | 69,581.33 |
|
|
47
|
+
| hyper-express | 66,356.707 | 80,002.53 | 69,953.76 | 49,113.83 |
|
|
48
48
|
| **ultimate-express** | **46,826.31** | **50,764.93** | **49,117.76** | **40,596.24** |
|
|
49
|
-
| h3
|
|
50
|
-
| fastify
|
|
51
|
-
| hono
|
|
52
|
-
| koa
|
|
53
|
-
| express
|
|
49
|
+
| h3 | 35,423.263 | 41,243.68 | 34,429.26 | 30,596.85 |
|
|
50
|
+
| fastify | 33,094.62 | 40,147.67 | 40,076.35 | 19,059.84 |
|
|
51
|
+
| hono | 26,576.02 | 36,215.35 | 34,656.12 | 8,856.59 |
|
|
52
|
+
| koa | 24,045.08 | 28,202.12 | 24,590.84 | 19,342.28 |
|
|
53
|
+
| express | 10,411.313 | 11,245.57 | 10,598.74 | 9,389.63 |
|
|
54
54
|
|
|
55
55
|
### Performance on real-world application
|
|
56
56
|
|
|
@@ -107,9 +107,11 @@ Optimized routes can be up to 10 times faster than normal routes, as they're usi
|
|
|
107
107
|
|
|
108
108
|
2. Do not use external `serve-static` module. Instead use built-in `express.static()` middleware, which is optimized for uExpress.
|
|
109
109
|
|
|
110
|
-
3. Do not
|
|
110
|
+
3. Do not use `body-parser` module. Instead use built-in `express.text()`, `express.json()` etc.
|
|
111
111
|
|
|
112
|
-
4.
|
|
112
|
+
4. Do not set `body methods` to read body of requests with GET method or other methods that don't need a body. Reading body makes server about 10k req/sec slower.
|
|
113
|
+
|
|
114
|
+
5. By default, µExpress creates 1 (or 0 if your CPU has only 1 core) child thread to improve performance of reading files. You can change this number by setting `threads` to a different number in `express()`, or set to 0 to disable thread pool (`express({ threads: 0 })`). Threads are shared between all express() instances, with largest `threads` number being used. Using more threads will not necessarily improve performance. Sometimes not using threads at all is faster, please [test](https://github.com/wg/wrk/) both options.
|
|
113
115
|
|
|
114
116
|
## WebSockets
|
|
115
117
|
|
|
@@ -133,7 +135,6 @@ In general, basically all features and options are supported. Use [Express 4.x d
|
|
|
133
135
|
- ✅ express.json()
|
|
134
136
|
- ✅ express.urlencoded()
|
|
135
137
|
- ✅ express.static()
|
|
136
|
-
- - Additionally you can pass `options.ifModifiedSince` to support If-Modified-Since header (this header is not supported in normal Express, but is supported in µExpress)
|
|
137
138
|
- ✅ express.text()
|
|
138
139
|
- ✅ express.raw()
|
|
139
140
|
- 🚧 express.request (this is not a constructor but a prototype for replacing methods)
|
|
@@ -253,7 +254,7 @@ In general, basically all features and options are supported. Use [Express 4.x d
|
|
|
253
254
|
- - ✅ Range header
|
|
254
255
|
- - ✅ Setting ETag header
|
|
255
256
|
- - ✅ If-Match header
|
|
256
|
-
- - ✅ If-Modified-Since header
|
|
257
|
+
- - ✅ If-Modified-Since header
|
|
257
258
|
- - ✅ If-Unmodified-Since header
|
|
258
259
|
- - ✅ If-Range header
|
|
259
260
|
- ✅ res.sendStatus()
|
|
@@ -281,7 +282,7 @@ In general, basically all features and options are supported. Use [Express 4.x d
|
|
|
281
282
|
|
|
282
283
|
Most of the middlewares that are compatible with Express are compatible with µExpress. Here's list of middlewares that we test for compatibility:
|
|
283
284
|
|
|
284
|
-
- ✅ [body-parser](https://npmjs.com/package/body-parser)
|
|
285
|
+
- ✅ [body-parser](https://npmjs.com/package/body-parser) (use `express.text()` etc instead for better performance)
|
|
285
286
|
- ✅ [cookie-parser](https://npmjs.com/package/cookie-parser)
|
|
286
287
|
- ✅ [cookie-session](https://npmjs.com/package/cookie-session)
|
|
287
288
|
- ✅ [serve-static](https://npmjs.com/package/serve-static) (use `express.static()` instead for better performance)
|
package/package.json
CHANGED
package/src/response.js
CHANGED
|
@@ -196,21 +196,23 @@ module.exports = class Response extends Writable {
|
|
|
196
196
|
if(data && !this.headers['etag'] && etagFn && !this.req.noEtag) {
|
|
197
197
|
this.set('etag', etagFn(data));
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.
|
|
204
|
-
this.socket.emit('close');
|
|
205
|
-
return this._res.end();
|
|
199
|
+
const fresh = this.req.fresh;
|
|
200
|
+
if(fresh) {
|
|
201
|
+
this._res.writeStatus('304');
|
|
202
|
+
} else {
|
|
203
|
+
this._res.writeStatus(this.statusCode.toString());
|
|
206
204
|
}
|
|
207
|
-
this._res.writeStatus(this.statusCode.toString());
|
|
208
205
|
for(const header in this.headers) {
|
|
209
206
|
if(header === 'content-length') {
|
|
210
207
|
continue;
|
|
211
208
|
}
|
|
212
209
|
this._res.writeHeader(header, this.headers[header]);
|
|
213
210
|
}
|
|
211
|
+
if(fresh) {
|
|
212
|
+
this.headersSent = true;
|
|
213
|
+
this.socket.emit('close');
|
|
214
|
+
return this._res.end();
|
|
215
|
+
}
|
|
214
216
|
if(!this.headers['content-type']) {
|
|
215
217
|
this._res.writeHeader('content-type', 'text/html' + (typeof data === 'string' ? `; charset=utf-8` : ''));
|
|
216
218
|
}
|
|
@@ -396,21 +398,6 @@ module.exports = class Response extends Writable {
|
|
|
396
398
|
return done(new Error('Precondition Failed'));
|
|
397
399
|
}
|
|
398
400
|
|
|
399
|
-
// if-modified-since
|
|
400
|
-
if(options.ifModifiedSince) {
|
|
401
|
-
let modifiedSince = this.req.headers['if-modified-since'];
|
|
402
|
-
let lastModified = this.headers['last-modified'];
|
|
403
|
-
if(options.lastModified && lastModified && modifiedSince) {
|
|
404
|
-
modifiedSince = parseHttpDate(modifiedSince);
|
|
405
|
-
lastModified = parseHttpDate(lastModified);
|
|
406
|
-
|
|
407
|
-
if(!isNaN(lastModified) && !isNaN(modifiedSince) && lastModified <= modifiedSince) {
|
|
408
|
-
this.status(304);
|
|
409
|
-
return this.end();
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
401
|
// range requests
|
|
415
402
|
let offset = 0, len = stat.size, ranged = false;
|
|
416
403
|
if(options.acceptRanges) {
|
|
@@ -440,6 +427,11 @@ module.exports = class Response extends Writable {
|
|
|
440
427
|
}
|
|
441
428
|
}
|
|
442
429
|
|
|
430
|
+
// if-modified-since, if-none-match
|
|
431
|
+
if(this.req.fresh) {
|
|
432
|
+
return this.end();
|
|
433
|
+
}
|
|
434
|
+
|
|
443
435
|
if(this.req.method === 'HEAD') {
|
|
444
436
|
this.set('Content-Length', stat.size);
|
|
445
437
|
return this.end();
|
|
@@ -576,7 +568,6 @@ module.exports = class Response extends Writable {
|
|
|
576
568
|
if(!options) {
|
|
577
569
|
options = {};
|
|
578
570
|
}
|
|
579
|
-
// TODO: signed cookies
|
|
580
571
|
let val = typeof value === 'object' ? "j:"+JSON.stringify(value) : String(value);
|
|
581
572
|
if(options.maxAge != null) {
|
|
582
573
|
const maxAge = options.maxAge - 0;
|