barejs 0.1.1 → 0.1.2
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/.github/workflows/bench.yml +34 -0
- package/README.md +8 -9
- package/benchmarks/index.ts +31 -0
- package/bun.lock +42 -4
- package/package.json +9 -2
- package/src/bare.ts +41 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Performance Benchmark
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [ main ]
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
benchmark:
|
|
8
|
+
name: Run Benchmark
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: oven-sh/setup-bun@v1
|
|
13
|
+
|
|
14
|
+
- name: Install dependencies
|
|
15
|
+
run: bun install
|
|
16
|
+
|
|
17
|
+
- name: Run Benchmarks
|
|
18
|
+
run: |
|
|
19
|
+
# รัน server benchmark ในพื้นหลัง
|
|
20
|
+
bun benchmarks/index.ts &
|
|
21
|
+
# รอให้ server พร้อม
|
|
22
|
+
sleep 5
|
|
23
|
+
# ใช้ bombardier ยิงและเก็บผลเป็น JSON
|
|
24
|
+
docker run --net=host alpine/bombardier -c 50 -d 10s -l http://localhost:3000/bench > result.json
|
|
25
|
+
|
|
26
|
+
- name: Store benchmark result
|
|
27
|
+
uses: benchmark-action/github-action-benchmark@v1
|
|
28
|
+
with:
|
|
29
|
+
tool: 'customBiggerIsBetter'
|
|
30
|
+
output-file-path: result.json
|
|
31
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
+
auto-push: true
|
|
33
|
+
# แสดงผลในหน้า GitHub Pages (Optional)
|
|
34
|
+
comment-always: true
|
package/README.md
CHANGED
|
@@ -5,15 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
BareJS isn't just another framework; it's a high-speed engine engineered to outpace the fastest tools in the Bun ecosystem by utilizing **Static Code Injection** and **Zero-Allocation** routing.
|
|
7
7
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
| Framework |
|
|
12
|
-
|
|
13
|
-
| **BareJS**
|
|
14
|
-
|
|
|
15
|
-
|
|
16
|
-
> **Result:** BareJS is **55.79% FASTER** than the competition.
|
|
8
|
+
## Performance 📊
|
|
9
|
+
Benchmark run on 12th Gen Intel(R) Core(TM) i7-12700 (Bun 1.3.0)
|
|
10
|
+
|
|
11
|
+
| Framework | Avg Latency | Comparison |
|
|
12
|
+
|-----------|-------------|------------|
|
|
13
|
+
| **BareJS**| **613.76 ns** | **🚀 Baseline** |
|
|
14
|
+
| Elysia | 1.39 µs | 2.2x Slower |
|
|
15
|
+
| Hono | 2.56 µs | 4.1x Slower |
|
|
17
16
|
|
|
18
17
|
---
|
|
19
18
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { run, bench, group } from "mitata";
|
|
2
|
+
import { BareJS } from "../src/bare";
|
|
3
|
+
import { Elysia } from "elysia";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
|
|
6
|
+
// Setup servers... (โค้ดเหมือนเดิม)
|
|
7
|
+
// แต่เปลี่ยนจากการ listen ค้างไว้ เป็นการใช้เครื่องมือวัดผลโดยตรง:
|
|
8
|
+
|
|
9
|
+
group("Web Framework Speed Test", () => {
|
|
10
|
+
const payload = { message: "bench" };
|
|
11
|
+
|
|
12
|
+
const bare = new BareJS();
|
|
13
|
+
bare.get("/", () => payload);
|
|
14
|
+
|
|
15
|
+
const elysia = new Elysia().get("/", () => payload);
|
|
16
|
+
const hono = new Hono().get("/", (c) => c.json(payload));
|
|
17
|
+
|
|
18
|
+
bench("BareJS (Your Engine)", async () => {
|
|
19
|
+
await bare.fetch(new Request("http://localhost/"));
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
bench("Elysia", async () => {
|
|
23
|
+
await elysia.handle(new Request("http://localhost/"));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
bench("Hono", async () => {
|
|
27
|
+
await hono.fetch(new Request("http://localhost/"));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await run();
|
package/bun.lock
CHANGED
|
@@ -3,22 +3,60 @@
|
|
|
3
3
|
"workspaces": {
|
|
4
4
|
"": {
|
|
5
5
|
"name": "barejs-release",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"elysia": "^1.4.21",
|
|
8
|
+
"hono": "^4.11.3",
|
|
9
|
+
"mitata": "^1.0.34",
|
|
10
|
+
},
|
|
6
11
|
"devDependencies": {
|
|
7
12
|
"@types/bun": "latest",
|
|
8
13
|
},
|
|
9
|
-
"peerDependencies": {
|
|
10
|
-
"typescript": "^5",
|
|
11
|
-
},
|
|
12
14
|
},
|
|
13
15
|
},
|
|
14
16
|
"packages": {
|
|
17
|
+
"@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="],
|
|
18
|
+
|
|
19
|
+
"@sinclair/typebox": ["@sinclair/typebox@0.34.46", "", {}, "sha512-kiW7CtS/NkdvTUjkjUJo7d5JsFfbJ14YjdhDk9KoEgK6nFjKNXZPrX0jfLA8ZlET4cFLHxOZ/0vFKOP+bOxIOQ=="],
|
|
20
|
+
|
|
21
|
+
"@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="],
|
|
22
|
+
|
|
23
|
+
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
|
24
|
+
|
|
15
25
|
"@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
|
|
16
26
|
|
|
17
27
|
"@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
|
18
28
|
|
|
19
29
|
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
|
20
30
|
|
|
21
|
-
"
|
|
31
|
+
"cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
|
32
|
+
|
|
33
|
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
34
|
+
|
|
35
|
+
"elysia": ["elysia@1.4.21", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.6", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-bGSbPSGnkWbO0qUDKS5Q+6iEewBdMmIiJ8F0li4djZ6WjpixUQouOzePYscG1Lemdv6pZpFi1YPfI/kjeq2voA=="],
|
|
36
|
+
|
|
37
|
+
"exact-mirror": ["exact-mirror@0.2.6", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA=="],
|
|
38
|
+
|
|
39
|
+
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
|
40
|
+
|
|
41
|
+
"file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],
|
|
42
|
+
|
|
43
|
+
"hono": ["hono@4.11.3", "", {}, "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w=="],
|
|
44
|
+
|
|
45
|
+
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
46
|
+
|
|
47
|
+
"memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],
|
|
48
|
+
|
|
49
|
+
"mitata": ["mitata@1.0.34", "", {}, "sha512-Mc3zrtNBKIMeHSCQ0XqRLo1vbdIx1wvFV9c8NJAiyho6AjNfMY8bVhbS12bwciUdd1t4rj8099CH3N3NFahaUA=="],
|
|
50
|
+
|
|
51
|
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
52
|
+
|
|
53
|
+
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
|
54
|
+
|
|
55
|
+
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
|
|
56
|
+
|
|
57
|
+
"token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="],
|
|
58
|
+
|
|
59
|
+
"uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
|
|
22
60
|
|
|
23
61
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
24
62
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "barejs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "High-performance JIT-specialized web framework for Bun",
|
|
5
5
|
"main": "src/bare.ts",
|
|
6
6
|
"types": "src/bare.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
+
"bench": "bun run benchmarks/index.ts",
|
|
11
|
+
"dev": "bun --watch src/bare.ts"
|
|
10
12
|
},
|
|
11
13
|
"keywords": [
|
|
12
14
|
"bun",
|
|
@@ -18,5 +20,10 @@
|
|
|
18
20
|
"license": "MIT",
|
|
19
21
|
"devDependencies": {
|
|
20
22
|
"@types/bun": "latest"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"elysia": "^1.4.21",
|
|
26
|
+
"hono": "^4.11.3",
|
|
27
|
+
"mitata": "^1.0.34"
|
|
21
28
|
}
|
|
22
29
|
}
|
package/src/bare.ts
CHANGED
|
@@ -12,13 +12,50 @@ export class BareJS {
|
|
|
12
12
|
private globalMiddlewares: Middleware[] = [];
|
|
13
13
|
private compiledFetch?: (req: Request) => Promise<Response>;
|
|
14
14
|
|
|
15
|
+
public post = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "POST", path, handlers: h }); return this; };
|
|
16
|
+
public put = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "PUT", path, handlers: h }); return this; };
|
|
17
|
+
public patch = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "PATCH", path, handlers: h }); return this; };
|
|
18
|
+
public delete = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "DELETE", path, handlers: h }); return this; };
|
|
15
19
|
public get = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "GET", path, handlers: h }); return this; };
|
|
16
|
-
public use = (m: Middleware) => { this.globalMiddlewares.push(m); return this; }
|
|
20
|
+
public use = (...m: Middleware[]) => { this.globalMiddlewares.push(...m); return this; }
|
|
21
|
+
public fetch = (req: Request): Promise<Response> | Response => {
|
|
22
|
+
if (!this.compiledFetch) this.compile();
|
|
23
|
+
return this.compiledFetch!(req);
|
|
24
|
+
}
|
|
25
|
+
// private compile() {
|
|
26
|
+
// let fnBody = "const gMW = this.globalMiddlewares; const allRoutes = this.routes; const EMPTY_PARAMS = Object.freeze({}); return async (req) => { const url = req.url; const pathStart = url.indexOf('/', 8); const path = pathStart === -1 ? '/' : url.substring(pathStart); const method = req.method;";
|
|
27
|
+
// // (Logic การ Compile เหมือนที่คุยกันไว้)
|
|
28
|
+
// fnBody += "return new Response('404', { status: 404 }); };";
|
|
29
|
+
// this.compiledFetch = new Function(fnBody).bind(this)();
|
|
30
|
+
// }
|
|
17
31
|
|
|
18
32
|
private compile() {
|
|
19
|
-
let fnBody =
|
|
20
|
-
|
|
21
|
-
|
|
33
|
+
let fnBody = `
|
|
34
|
+
const gMW = this.globalMiddlewares;
|
|
35
|
+
const EMPTY_PARAMS = Object.freeze({});
|
|
36
|
+
return async (req) => {
|
|
37
|
+
const url = req.url;
|
|
38
|
+
const pathStart = url.indexOf('/', 8);
|
|
39
|
+
const path = pathStart === -1 ? '/' : url.substring(pathStart);
|
|
40
|
+
const method = req.method;
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < this.routes.length; i++) {
|
|
45
|
+
const route = this.routes[i];
|
|
46
|
+
|
|
47
|
+
if (route) {
|
|
48
|
+
fnBody += `
|
|
49
|
+
if (method === '${route.method}' && path === '${route.path}') {
|
|
50
|
+
const ctx = { req, params: EMPTY_PARAMS, json: (d) => Response.json(d) };
|
|
51
|
+
// รัน Handler ตัวแรกของ Route นี้
|
|
52
|
+
return this.routes[${i}].handlers[0](ctx);
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fnBody += "return new Response('404 Not Found', { status: 404 }); };";
|
|
22
59
|
this.compiledFetch = new Function(fnBody).bind(this)();
|
|
23
60
|
}
|
|
24
61
|
|