frontend-hamroun 1.2.51 → 1.2.52
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 +663 -124
- package/package.json +1 -1
package/README.md
CHANGED
@@ -1,29 +1,67 @@
|
|
1
|
-
|
1
|
+
<div align="center">
|
2
2
|
|
3
|
-
|
3
|
+
# 🚀 Frontend Hamroun
|
4
4
|
|
5
|
-
|
6
|
-

|
7
|
-

|
8
|
-

|
5
|
+
A lightweight full-stack JavaScript framework with Virtual DOM and hooks implementation
|
9
6
|
|
10
|
-
|
7
|
+
[](https://www.npmjs.com/package/frontend-hamroun)
|
8
|
+
[](https://bundlephobia.com/result?p=frontend-hamroun)
|
9
|
+
[](https://www.npmjs.com/package/frontend-hamroun)
|
10
|
+
[](LICENSE)
|
11
|
+
|
12
|
+
<img src="https://via.placeholder.com/800x400?text=Frontend+Hamroun+Framework" alt="Framework Banner" width="800" style="border-radius: 10px;"/>
|
13
|
+
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<br>
|
17
|
+
|
18
|
+
## 📋 Contents
|
19
|
+
|
20
|
+
- [Installation](#-installation)
|
21
|
+
- [Quick Start](#-quick-start)
|
22
|
+
- [Features](#-features)
|
23
|
+
- [Client-side Features](#-client-side-features)
|
24
|
+
- [Server-side Features](#-server-side-features)
|
25
|
+
- [Server-Side Rendering](#-server-side-rendering)
|
26
|
+
- [Performance Optimization](#-performance-optimization)
|
27
|
+
- [CLI Tools](#-cli-tools)
|
28
|
+
- [TypeScript Support](#-typescript-support)
|
29
|
+
- [Browser Compatibility](#-browser-compatibility)
|
30
|
+
- [Contributing](#-contributing)
|
31
|
+
- [Documentation](#-documentation)
|
32
|
+
|
33
|
+
<br>
|
34
|
+
|
35
|
+
## 🔌 Installation
|
11
36
|
|
12
37
|
```bash
|
13
38
|
npm install frontend-hamroun
|
14
39
|
```
|
15
40
|
|
16
|
-
|
41
|
+
<div align="center">
|
42
|
+
|
43
|
+
### ✨ Quick Links
|
44
|
+
|
45
|
+
[](https://github.com/hamroun/frontend-hamroun)
|
46
|
+
[](https://github.com/hamroun/frontend-hamroun/examples)
|
47
|
+
[](https://github.com/hamroun/frontend-hamroun/docs/API.md)
|
48
|
+
[](https://discord.gg/frontendhamroun)
|
49
|
+
|
50
|
+
</div>
|
51
|
+
|
52
|
+
## 🚀 Quick Start
|
17
53
|
|
18
|
-
Create a new project
|
54
|
+
Create a new project with a single command:
|
19
55
|
|
20
56
|
```bash
|
57
|
+
# Using create-frontend-app
|
21
58
|
npx create-frontend-app my-app
|
22
|
-
|
59
|
+
|
60
|
+
# Or using the frontend-hamroun CLI
|
23
61
|
npx frontend-hamroun create my-app
|
24
62
|
```
|
25
63
|
|
26
|
-
Then:
|
64
|
+
Then launch your new project:
|
27
65
|
|
28
66
|
```bash
|
29
67
|
cd my-app
|
@@ -31,17 +69,92 @@ npm install
|
|
31
69
|
npm run dev
|
32
70
|
```
|
33
71
|
|
34
|
-
|
72
|
+
<div align="center">
|
73
|
+
|
74
|
+
### 🎮 Interactive Demo
|
75
|
+
|
76
|
+
[](https://codesandbox.io)
|
77
|
+
[](https://stackblitz.com)
|
78
|
+
|
79
|
+
</div>
|
80
|
+
|
81
|
+
## 🎯 Features
|
82
|
+
|
83
|
+
<div class="features-grid" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
|
84
|
+
|
85
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
86
|
+
<h3>🔍 Lightweight Core</h3>
|
87
|
+
<p><strong><5KB</strong> gzipped for essential runtime</p>
|
88
|
+
</div>
|
89
|
+
|
90
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
91
|
+
<h3>⚡ Full-Stack Solution</h3>
|
92
|
+
<p>Client and server capabilities in one package</p>
|
93
|
+
</div>
|
94
|
+
|
95
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
96
|
+
<h3>🔄 Virtual DOM</h3>
|
97
|
+
<p>Efficient rendering and diffing algorithm</p>
|
98
|
+
</div>
|
99
|
+
|
100
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
101
|
+
<h3>🪝 Hooks API</h3>
|
102
|
+
<p>Complete hooks system for state management</p>
|
103
|
+
</div>
|
104
|
+
|
105
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
106
|
+
<h3>🌐 Server-Side Rendering</h3>
|
107
|
+
<p>Optimized SSR with hydration</p>
|
108
|
+
</div>
|
109
|
+
|
110
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
111
|
+
<h3>🔐 Authentication</h3>
|
112
|
+
<p>Built-in JWT authentication system</p>
|
113
|
+
</div>
|
114
|
+
|
115
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
116
|
+
<h3>💾 Database Integration</h3>
|
117
|
+
<p>Support for MongoDB, MySQL, PostgreSQL</p>
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<div class="feature-card" style="background: #f8f9fa; border-radius: 8px; padding: 20px;">
|
121
|
+
<h3>🧩 TypeScript Support</h3>
|
122
|
+
<p>Full type definitions included</p>
|
123
|
+
</div>
|
124
|
+
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<br>
|
128
|
+
|
129
|
+
## 📊 Framework Comparison
|
130
|
+
|
131
|
+
| Feature | Frontend Hamroun | React | Vue | Angular |
|
132
|
+
|---------|------------------|-------|-----|---------|
|
133
|
+
| Bundle Size | < 5KB | 42KB | 33KB | 65KB |
|
134
|
+
| Virtual DOM | ✅ | ✅ | ✅ | ❌ |
|
135
|
+
| Hooks API | ✅ | ✅ | ⚠️ | ❌ |
|
136
|
+
| Built-in SSR | ✅ | ❌ | ⚠️ | ✅ |
|
137
|
+
| Built-in API Server | ✅ | ❌ | ❌ | ❌ |
|
138
|
+
| DB Integration | ✅ | ❌ | ❌ | ❌ |
|
139
|
+
| Learning Curve | Low | Medium | Low | High |
|
140
|
+
|
141
|
+
<br>
|
142
|
+
|
143
|
+
## 💻 Basic Usage
|
35
144
|
|
36
145
|
```jsx
|
37
146
|
import { render, useState } from 'frontend-hamroun';
|
38
147
|
|
39
148
|
function App() {
|
40
149
|
const [count, setCount] = useState(0);
|
150
|
+
|
41
151
|
return (
|
42
|
-
<div>
|
43
|
-
<h1>
|
44
|
-
<
|
152
|
+
<div className="app">
|
153
|
+
<h1>Frontend Hamroun Demo</h1>
|
154
|
+
<p>Count: {count}</p>
|
155
|
+
<button onClick={() => setCount(count + 1)}>
|
156
|
+
Increment
|
157
|
+
</button>
|
45
158
|
</div>
|
46
159
|
);
|
47
160
|
}
|
@@ -49,116 +162,161 @@ function App() {
|
|
49
162
|
render(<App />, document.getElementById('root'));
|
50
163
|
```
|
51
164
|
|
52
|
-
|
165
|
+
<div align="center">
|
166
|
+
<img src="https://via.placeholder.com/600x300?text=Application+Screenshot" alt="Application Screenshot" width="600" style="border-radius: 8px;"/>
|
167
|
+
</div>
|
53
168
|
|
54
|
-
|
55
|
-
- Virtual DOM with efficient diffing algorithm
|
56
|
-
- Hooks API (useState, useEffect, useMemo, useRef)
|
57
|
-
- Context API for state management
|
58
|
-
- Server-Side Rendering
|
59
|
-
- Built-in API server with Express
|
60
|
-
- Database integration (MongoDB, MySQL, PostgreSQL)
|
61
|
-
- Authentication with JWT
|
62
|
-
- Error Boundaries
|
63
|
-
- JSX support
|
64
|
-
- TypeScript support
|
65
|
-
- Interactive CLI for project scaffolding
|
169
|
+
## 🧩 Client-side Features
|
66
170
|
|
67
|
-
|
171
|
+
### Component Development
|
68
172
|
|
69
|
-
|
173
|
+
Frontend Hamroun provides a React-like development experience:
|
70
174
|
|
71
|
-
|
72
|
-
|
175
|
+
```jsx
|
176
|
+
import { useState, useEffect } from 'frontend-hamroun';
|
73
177
|
|
178
|
+
function Counter() {
|
179
|
+
const [count, setCount] = useState(0);
|
180
|
+
|
181
|
+
useEffect(() => {
|
182
|
+
document.title = `Count: ${count}`;
|
183
|
+
return () => document.title = 'App';
|
184
|
+
}, [count]);
|
185
|
+
|
186
|
+
return (
|
187
|
+
<div className="counter">
|
188
|
+
<h2>Counter: {count}</h2>
|
189
|
+
<div className="buttons">
|
190
|
+
<button onClick={() => setCount(count + 1)}>+</button>
|
191
|
+
<button onClick={() => setCount(count - 1)}>-</button>
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
);
|
195
|
+
}
|
196
|
+
```
|
197
|
+
|
198
|
+
<details>
|
199
|
+
<summary><b>🔍 View Hooks API Reference</b></summary>
|
200
|
+
|
201
|
+
### Hooks System
|
202
|
+
|
203
|
+
#### 🔄 useState
|
74
204
|
```jsx
|
75
205
|
const [count, setCount] = useState(0);
|
76
|
-
setCount(count + 1); // Direct
|
77
|
-
setCount(prev => prev + 1); //
|
206
|
+
setCount(count + 1); // Direct update
|
207
|
+
setCount(prev => prev + 1); // Functional update
|
78
208
|
```
|
79
209
|
|
80
|
-
#### useEffect
|
81
|
-
Handles side effects in components.
|
82
|
-
|
210
|
+
#### 🔄 useEffect
|
83
211
|
```jsx
|
84
212
|
useEffect(() => {
|
85
|
-
|
213
|
+
// Effect logic
|
214
|
+
const subscription = api.subscribe();
|
86
215
|
|
87
216
|
return () => {
|
88
|
-
// Cleanup
|
89
|
-
|
217
|
+
// Cleanup logic
|
218
|
+
subscription.unsubscribe();
|
90
219
|
};
|
91
|
-
}, [
|
220
|
+
}, [dependency]); // Dependency array
|
92
221
|
```
|
93
222
|
|
94
|
-
#### useMemo
|
95
|
-
Memoizes expensive computations.
|
96
|
-
|
223
|
+
#### 🔄 useMemo
|
97
224
|
```jsx
|
98
|
-
const
|
99
|
-
|
100
|
-
|
101
|
-
}, [count]);
|
225
|
+
const expensiveValue = useMemo(() => {
|
226
|
+
return computeExpensiveValue(a, b);
|
227
|
+
}, [a, b]); // Recomputes only when a or b changes
|
102
228
|
```
|
103
229
|
|
104
|
-
#### useRef
|
105
|
-
Creates a mutable reference that persists across renders.
|
106
|
-
|
230
|
+
#### 🔄 useRef
|
107
231
|
```jsx
|
108
|
-
const
|
109
|
-
|
110
|
-
|
232
|
+
const inputRef = useRef(null);
|
233
|
+
|
234
|
+
// Access the DOM element directly
|
235
|
+
useEffect(() => {
|
236
|
+
inputRef.current.focus();
|
237
|
+
}, []);
|
111
238
|
|
112
|
-
|
113
|
-
|
239
|
+
return <input ref={inputRef} />;
|
240
|
+
```
|
114
241
|
|
242
|
+
#### 🔄 useErrorBoundary
|
115
243
|
```jsx
|
116
244
|
const [error, resetError] = useErrorBoundary();
|
117
245
|
|
118
246
|
if (error) {
|
119
247
|
return (
|
120
|
-
<div>
|
121
|
-
<
|
248
|
+
<div className="error-boundary">
|
249
|
+
<h2>Something went wrong</h2>
|
250
|
+
<p>{error.message}</p>
|
122
251
|
<button onClick={resetError}>Try again</button>
|
123
252
|
</div>
|
124
253
|
);
|
125
254
|
}
|
126
255
|
```
|
127
256
|
|
128
|
-
|
257
|
+
</details>
|
258
|
+
|
259
|
+
### 🔄 Context API
|
129
260
|
|
130
|
-
Share state across
|
261
|
+
Share state across your component tree:
|
262
|
+
|
263
|
+
<div class="code-with-diagram" style="display: flex; align-items: flex-start; gap: 20px;">
|
131
264
|
|
132
265
|
```jsx
|
133
266
|
// Create context
|
134
267
|
const ThemeContext = createContext('light');
|
135
268
|
|
136
|
-
// Provider
|
269
|
+
// Provider
|
137
270
|
function App() {
|
138
271
|
const [theme, setTheme] = useState('light');
|
139
272
|
|
140
273
|
return (
|
141
274
|
<ThemeContext.Provider value={theme}>
|
142
|
-
<
|
143
|
-
|
144
|
-
|
145
|
-
|
275
|
+
<Header />
|
276
|
+
<Main />
|
277
|
+
<button onClick={() => setTheme(
|
278
|
+
theme === 'light' ? 'dark' : 'light'
|
279
|
+
)}>
|
280
|
+
Toggle theme
|
281
|
+
</button>
|
146
282
|
</ThemeContext.Provider>
|
147
283
|
);
|
148
284
|
}
|
149
285
|
|
150
|
-
// Consumer
|
151
|
-
function
|
286
|
+
// Consumer
|
287
|
+
function Header() {
|
152
288
|
const theme = useContext(ThemeContext);
|
153
|
-
return
|
154
|
-
|
155
|
-
|
289
|
+
return (
|
290
|
+
<header className={theme}>
|
291
|
+
<h1>My App</h1>
|
292
|
+
</header>
|
293
|
+
);
|
156
294
|
}
|
157
295
|
```
|
158
296
|
|
159
|
-
|
160
|
-
|
161
|
-
|
297
|
+
<div class="diagram" style="background: #f8f9fa; border-radius: 8px; padding: 15px; width: 300px;">
|
298
|
+
<strong>Context Flow Diagram</strong><br>
|
299
|
+
<pre style="background: #f0f0f0; padding: 10px; margin-top: 10px; border-radius: 5px;">
|
300
|
+
App (Provider)
|
301
|
+
│
|
302
|
+
├─► Header (Consumer)
|
303
|
+
│ Uses theme value
|
304
|
+
│
|
305
|
+
├─► Main
|
306
|
+
│ │
|
307
|
+
│ └─► Article (Consumer)
|
308
|
+
│ Uses theme value
|
309
|
+
│
|
310
|
+
└─► Footer (Consumer)
|
311
|
+
Uses theme value
|
312
|
+
</pre>
|
313
|
+
</div>
|
314
|
+
|
315
|
+
</div>
|
316
|
+
|
317
|
+
## 🖥️ Server-Side Features
|
318
|
+
|
319
|
+
### Express Server Integration
|
162
320
|
|
163
321
|
```js
|
164
322
|
import { server } from 'frontend-hamroun/server';
|
@@ -169,7 +327,7 @@ const app = await server.createServer({
|
|
169
327
|
pagesDir: './pages',
|
170
328
|
staticDir: './public',
|
171
329
|
db: {
|
172
|
-
url: process.env.
|
330
|
+
url: process.env.DATABASE_URL,
|
173
331
|
type: 'mongodb' // or 'mysql', 'postgres'
|
174
332
|
},
|
175
333
|
auth: {
|
@@ -179,101 +337,482 @@ const app = await server.createServer({
|
|
179
337
|
});
|
180
338
|
|
181
339
|
await app.start();
|
340
|
+
console.log('Server running at http://localhost:3000');
|
182
341
|
```
|
183
342
|
|
343
|
+
<div align="center">
|
344
|
+
<img src="https://via.placeholder.com/600x300?text=Server+Architecture+Diagram" alt="Server Architecture" width="600" style="border-radius: 8px;"/>
|
345
|
+
</div>
|
346
|
+
|
184
347
|
### API Routes
|
185
348
|
|
186
|
-
Create API endpoints
|
349
|
+
Create API endpoints easily with file-based routing:
|
350
|
+
|
351
|
+
<div class="file-structure" style="display: flex; gap: 20px;">
|
352
|
+
|
353
|
+
<div class="code-example" style="flex: 1;">
|
187
354
|
|
188
355
|
```js
|
189
|
-
// api/users.js
|
356
|
+
// api/users.js - Automatically mapped to /api/users
|
190
357
|
export async function get(req, res) {
|
191
358
|
const users = await req.db.collection('users').find().toArray();
|
192
359
|
res.json(users);
|
193
360
|
}
|
194
361
|
|
195
362
|
export async function post(req, res) {
|
196
|
-
const
|
197
|
-
|
363
|
+
const { name, email } = req.body;
|
364
|
+
|
365
|
+
if (!name || !email) {
|
366
|
+
return res.status(400).json({
|
367
|
+
error: 'Name and email are required'
|
368
|
+
});
|
369
|
+
}
|
370
|
+
|
371
|
+
const result = await req.db.collection('users').insertOne({
|
372
|
+
name,
|
373
|
+
email
|
374
|
+
});
|
375
|
+
|
198
376
|
res.status(201).json(result);
|
199
377
|
}
|
200
378
|
```
|
201
379
|
|
202
|
-
|
380
|
+
</div>
|
381
|
+
|
382
|
+
<div class="file-structure-diagram" style="background: #f8f9fa; border-radius: 8px; padding: 15px; min-width: 250px;">
|
383
|
+
<strong>File-based Routing</strong><br>
|
384
|
+
<pre style="background: #f0f0f0; padding: 10px; margin-top: 10px; border-radius: 5px;">
|
385
|
+
api/
|
386
|
+
├── users.js
|
387
|
+
│ ├── get() → GET /api/users
|
388
|
+
│ └── post() → POST /api/users
|
389
|
+
├── posts/
|
390
|
+
│ ├── index.js
|
391
|
+
│ │ └── get() → GET /api/posts
|
392
|
+
│ └── [id].js
|
393
|
+
│ └── get() → GET /api/posts/:id
|
394
|
+
└── auth/
|
395
|
+
├── login.js
|
396
|
+
│ └── post() → POST /api/auth/login
|
397
|
+
└── register.js
|
398
|
+
└── post() → POST /api/auth/register
|
399
|
+
</pre>
|
400
|
+
</div>
|
401
|
+
|
402
|
+
</div>
|
403
|
+
|
404
|
+
<details>
|
405
|
+
<summary><b>🔍 View Database Integration Examples</b></summary>
|
406
|
+
|
407
|
+
### 💾 Database Integration
|
408
|
+
|
409
|
+
Access your database directly in API routes:
|
410
|
+
|
411
|
+
<div class="tabs">
|
412
|
+
<div class="tab" id="mongodb">
|
413
|
+
|
414
|
+
#### MongoDB Example
|
415
|
+
|
416
|
+
```js
|
417
|
+
// MongoDB example
|
418
|
+
export async function get(req, res) {
|
419
|
+
const { id } = req.params;
|
420
|
+
const user = await req.db.collection('users').findOne({
|
421
|
+
_id: new ObjectId(id)
|
422
|
+
});
|
423
|
+
|
424
|
+
if (!user) {
|
425
|
+
return res.status(404).json({ error: 'User not found' });
|
426
|
+
}
|
427
|
+
|
428
|
+
res.json(user);
|
429
|
+
}
|
430
|
+
```
|
431
|
+
|
432
|
+
</div>
|
433
|
+
<div class="tab" id="mysql">
|
203
434
|
|
204
|
-
|
435
|
+
#### MySQL Example
|
436
|
+
|
437
|
+
```js
|
438
|
+
// MySQL example
|
439
|
+
export async function get(req, res) {
|
440
|
+
const [users] = await req.db.execute(
|
441
|
+
'SELECT * FROM users WHERE active = ?',
|
442
|
+
[true]
|
443
|
+
);
|
444
|
+
res.json(users);
|
445
|
+
}
|
446
|
+
```
|
447
|
+
|
448
|
+
</div>
|
449
|
+
<div class="tab" id="postgres">
|
450
|
+
|
451
|
+
#### PostgreSQL Example
|
452
|
+
|
453
|
+
```js
|
454
|
+
// PostgreSQL example
|
455
|
+
export async function get(req, res) {
|
456
|
+
const result = await req.db.query(
|
457
|
+
'SELECT * FROM users WHERE role = $1',
|
458
|
+
['admin']
|
459
|
+
);
|
460
|
+
res.json(result.rows);
|
461
|
+
}
|
462
|
+
```
|
463
|
+
|
464
|
+
</div>
|
465
|
+
</div>
|
466
|
+
|
467
|
+
</details>
|
468
|
+
|
469
|
+
<details>
|
470
|
+
<summary><b>🔍 View Authentication Example</b></summary>
|
471
|
+
|
472
|
+
### 🔐 Authentication
|
473
|
+
|
474
|
+
Built-in JWT authentication:
|
475
|
+
|
476
|
+
```js
|
477
|
+
// api/auth/login.js
|
478
|
+
export async function post(req, res) {
|
479
|
+
const { username, password } = req.body;
|
480
|
+
const user = await req.db.collection('users').findOne({ username });
|
481
|
+
|
482
|
+
if (!user || !await req.auth.comparePasswords(password, user.password)) {
|
483
|
+
return res.status(401).json({ error: 'Invalid credentials' });
|
484
|
+
}
|
485
|
+
|
486
|
+
const token = req.auth.generateToken(user);
|
487
|
+
res.json({
|
488
|
+
token,
|
489
|
+
user: { id: user._id, username: user.username }
|
490
|
+
});
|
491
|
+
}
|
492
|
+
|
493
|
+
// Protected route
|
494
|
+
// api/profile.js
|
495
|
+
export async function get(req, res) {
|
496
|
+
// req.auth.requireAuth middleware automatically added
|
497
|
+
// req.user contains the authenticated user
|
498
|
+
res.json(req.user);
|
499
|
+
}
|
500
|
+
```
|
501
|
+
|
502
|
+
</details>
|
503
|
+
|
504
|
+
<details>
|
505
|
+
<summary><b>🔍 View Middleware Example</b></summary>
|
506
|
+
|
507
|
+
### Middleware Support
|
508
|
+
|
509
|
+
Add custom middleware to your routes:
|
510
|
+
|
511
|
+
```js
|
512
|
+
// middleware/logger.js
|
513
|
+
export default function logger(req, res, next) {
|
514
|
+
console.log(`${req.method} ${req.path}`);
|
515
|
+
next();
|
516
|
+
}
|
517
|
+
|
518
|
+
// server.js
|
519
|
+
import logger from './middleware/logger';
|
520
|
+
|
521
|
+
const app = await server.createServer({
|
522
|
+
// ...other options
|
523
|
+
middleware: [logger]
|
524
|
+
});
|
525
|
+
```
|
526
|
+
|
527
|
+
</details>
|
528
|
+
|
529
|
+
## 🌐 Server-Side Rendering
|
530
|
+
|
531
|
+
Frontend Hamroun provides seamless SSR with hydration:
|
532
|
+
|
533
|
+
<div class="ssr-diagram-container" style="display: flex; gap: 20px; margin-bottom: 20px;">
|
534
|
+
|
535
|
+
<div class="code-example" style="flex: 1;">
|
205
536
|
|
206
537
|
```jsx
|
207
|
-
//
|
538
|
+
// server.js
|
208
539
|
import { renderToString } from 'frontend-hamroun/ssr';
|
540
|
+
import App from './App';
|
541
|
+
|
542
|
+
app.get('*', async (req, res) => {
|
543
|
+
const html = await renderToString(<App url={req.url} />);
|
544
|
+
|
545
|
+
res.send(`
|
546
|
+
<!DOCTYPE html>
|
547
|
+
<html>
|
548
|
+
<head>
|
549
|
+
<title>My SSR App</title>
|
550
|
+
<link rel="stylesheet" href="/styles.css">
|
551
|
+
</head>
|
552
|
+
<body>
|
553
|
+
<div id="root">${html}</div>
|
554
|
+
<script src="/client.js"></script>
|
555
|
+
</body>
|
556
|
+
</html>
|
557
|
+
`);
|
558
|
+
});
|
209
559
|
|
210
|
-
|
211
|
-
res.send(`
|
212
|
-
<!DOCTYPE html>
|
213
|
-
<html>
|
214
|
-
<head><title>My App</title></head>
|
215
|
-
<body>
|
216
|
-
<div id="root">${html}</div>
|
217
|
-
<script src="/client.js"></script>
|
218
|
-
</body>
|
219
|
-
</html>
|
220
|
-
`);
|
221
|
-
|
222
|
-
// Client-side
|
560
|
+
// client.js
|
223
561
|
import { hydrate } from 'frontend-hamroun';
|
562
|
+
import App from './App';
|
224
563
|
|
225
|
-
hydrate(<App />,
|
564
|
+
hydrate(<App url={window.location.pathname} />,
|
565
|
+
document.getElementById('root'));
|
226
566
|
```
|
227
567
|
|
228
|
-
|
568
|
+
</div>
|
569
|
+
|
570
|
+
<div class="ssr-flow-diagram" style="background: #f8f9fa; border-radius: 8px; padding: 15px; min-width: 250px;">
|
571
|
+
<strong>SSR Flow</strong><br>
|
572
|
+
<pre style="background: #f0f0f0; padding: 10px; margin-top: 10px; border-radius: 5px;">
|
573
|
+
1. HTTP Request
|
574
|
+
↓
|
575
|
+
2. Server renders React to HTML
|
576
|
+
↓
|
577
|
+
3. HTML sent to browser
|
578
|
+
↓
|
579
|
+
4. Browser displays HTML
|
580
|
+
↓
|
581
|
+
5. JavaScript loads
|
582
|
+
↓
|
583
|
+
6. Hydration attaches event
|
584
|
+
handlers to existing DOM
|
585
|
+
↓
|
586
|
+
7. App becomes interactive
|
587
|
+
</pre>
|
588
|
+
</div>
|
589
|
+
|
590
|
+
</div>
|
591
|
+
|
592
|
+
<div align="center">
|
593
|
+
<img src="https://via.placeholder.com/700x200?text=SSR+vs+CSR+Performance+Comparison" alt="SSR Performance" width="700" style="border-radius: 8px;"/>
|
594
|
+
</div>
|
595
|
+
|
596
|
+
## ⚡ Performance Optimization
|
229
597
|
|
230
598
|
### Batch Updates
|
231
|
-
|
599
|
+
|
600
|
+
Group state updates for better performance:
|
232
601
|
|
233
602
|
```jsx
|
234
603
|
import { batchUpdates } from 'frontend-hamroun';
|
235
604
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
});
|
605
|
+
function handleSubmit() {
|
606
|
+
batchUpdates(() => {
|
607
|
+
setSubmitting(true);
|
608
|
+
setFormData({ name: '', email: '' });
|
609
|
+
setErrors({});
|
610
|
+
setSubmitCount(c => c + 1);
|
611
|
+
});
|
612
|
+
}
|
613
|
+
```
|
614
|
+
|
615
|
+
### Virtual DOM Diffing
|
616
|
+
|
617
|
+
The framework uses an efficient diffing algorithm to minimize DOM operations:
|
618
|
+
|
619
|
+
<div class="diffing-container" style="display: flex; gap: 20px; margin-bottom: 20px;">
|
620
|
+
|
621
|
+
<div class="code-example" style="flex: 1;">
|
622
|
+
|
623
|
+
```jsx
|
624
|
+
// This only updates the changed parts of the DOM
|
625
|
+
function Counter() {
|
626
|
+
const [count, setCount] = useState(0);
|
627
|
+
return (
|
628
|
+
<div>
|
629
|
+
<h1>Counter</h1>
|
630
|
+
<p>Count: {count}</p> {/* Only this text node updates */}
|
631
|
+
<button onClick={() => setCount(count + 1)}>
|
632
|
+
Increment
|
633
|
+
</button>
|
634
|
+
</div>
|
635
|
+
);
|
636
|
+
}
|
241
637
|
```
|
242
638
|
|
243
|
-
|
639
|
+
</div>
|
640
|
+
|
641
|
+
<div class="diffing-diagram" style="background: #f8f9fa; border-radius: 8px; padding: 15px; min-width: 250px;">
|
642
|
+
<strong>Diffing Process</strong><br>
|
643
|
+
<pre style="background: #f0f0f0; padding: 10px; margin-top: 10px; border-radius: 5px;">
|
644
|
+
Old Virtual DOM
|
645
|
+
↓
|
646
|
+
New Virtual DOM
|
647
|
+
↓
|
648
|
+
Compare Trees
|
649
|
+
↓
|
650
|
+
Identify Differences
|
651
|
+
↓
|
652
|
+
Update Only Changed
|
653
|
+
DOM Elements
|
654
|
+
</pre>
|
655
|
+
</div>
|
244
656
|
|
245
|
-
|
657
|
+
</div>
|
246
658
|
|
247
|
-
|
248
|
-
|
249
|
-
|
659
|
+
<div align="center">
|
660
|
+
<img src="https://via.placeholder.com/700x200?text=Performance+Benchmark+Graph" alt="Performance Benchmark" width="700" style="border-radius: 8px;"/>
|
661
|
+
</div>
|
250
662
|
|
251
|
-
## CLI Tools
|
663
|
+
## 🛠️ CLI Tools
|
252
664
|
|
253
|
-
Frontend Hamroun
|
665
|
+
Frontend Hamroun includes powerful CLI tools for development:
|
666
|
+
|
667
|
+
<div class="cli-examples" style="background: #f8f9fa; border-radius: 8px; padding: 20px; margin-bottom: 20px;">
|
254
668
|
|
255
669
|
```bash
|
256
|
-
# Create a new project
|
670
|
+
# Create a new project with interactive template selection
|
257
671
|
npx frontend-hamroun create my-app
|
258
672
|
|
259
|
-
#
|
673
|
+
# Generate a new component with customizable features
|
260
674
|
npx frontend-hamroun add:component Button
|
261
675
|
|
262
|
-
#
|
263
|
-
npx frontend-hamroun add:page
|
264
|
-
|
265
|
-
# Add a new API route
|
266
|
-
npx frontend-hamroun add:api users
|
267
|
-
```
|
268
|
-
|
269
|
-
## Browser Compatibility
|
676
|
+
# Create a new page component
|
677
|
+
npx frontend-hamroun add:page Home
|
270
678
|
|
271
|
-
|
679
|
+
# Generate an API route
|
680
|
+
npx frontend-hamroun add:api users --methods=get,post,put,delete
|
272
681
|
|
273
|
-
|
682
|
+
# View development tools and tips
|
683
|
+
npx frontend-hamroun dev:tools
|
684
|
+
```
|
274
685
|
|
275
|
-
|
686
|
+
</div>
|
687
|
+
|
688
|
+
### 📦 Project Templates
|
689
|
+
|
690
|
+
<div class="templates-container" style="display: flex; gap: 20px; overflow-x: auto; padding-bottom: 15px; margin-bottom: 20px;">
|
691
|
+
|
692
|
+
<div class="template-card" style="background: #f0f5ff; border-radius: 8px; padding: 15px; min-width: 250px; border-left: 5px solid #4285f4;">
|
693
|
+
<h3>🚀 Basic App</h3>
|
694
|
+
<p>Client-side SPA with essential features</p>
|
695
|
+
<ul>
|
696
|
+
<li>Quick setup</li>
|
697
|
+
<li>No build step in development</li>
|
698
|
+
<li>Focused on simplicity</li>
|
699
|
+
<li>Perfect for learning</li>
|
700
|
+
</ul>
|
701
|
+
</div>
|
702
|
+
|
703
|
+
<div class="template-card" style="background: #f0fff4; border-radius: 8px; padding: 15px; min-width: 250px; border-left: 5px solid #34a853;">
|
704
|
+
<h3>🌐 SSR Template</h3>
|
705
|
+
<p>Server-side rendering with hydration</p>
|
706
|
+
<ul>
|
707
|
+
<li>SEO-friendly</li>
|
708
|
+
<li>Fast initial load</li>
|
709
|
+
<li>Express server included</li>
|
710
|
+
<li>Optimized for content sites</li>
|
711
|
+
</ul>
|
712
|
+
</div>
|
713
|
+
|
714
|
+
<div class="template-card" style="background: #fff8e1; border-radius: 8px; padding: 15px; min-width: 250px; border-left: 5px solid #fbbc04;">
|
715
|
+
<h3>⚡ Fullstack App</h3>
|
716
|
+
<p>Complete solution with API, authentication, and database</p>
|
717
|
+
<ul>
|
718
|
+
<li>API routes included</li>
|
719
|
+
<li>Database integration</li>
|
720
|
+
<li>Authentication ready</li>
|
721
|
+
<li>Production-ready setup</li>
|
722
|
+
</ul>
|
723
|
+
</div>
|
724
|
+
|
725
|
+
</div>
|
726
|
+
|
727
|
+
## 📘 TypeScript Support
|
728
|
+
|
729
|
+
Frontend Hamroun is built with TypeScript and includes full type definitions:
|
730
|
+
|
731
|
+
```tsx
|
732
|
+
import { useState } from 'frontend-hamroun';
|
733
|
+
|
734
|
+
interface UserProps {
|
735
|
+
id: number;
|
736
|
+
name: string;
|
737
|
+
email: string;
|
738
|
+
}
|
276
739
|
|
277
|
-
|
740
|
+
function UserProfile({ id, name, email }: UserProps) {
|
741
|
+
const [isEditing, setEditing] = useState(false);
|
742
|
+
|
743
|
+
return (
|
744
|
+
<div className="user-profile">
|
745
|
+
<h2>{name}</h2>
|
746
|
+
<p>{email}</p>
|
747
|
+
<button onClick={() => setEditing(!isEditing)}>
|
748
|
+
{isEditing ? 'Cancel' : 'Edit'}
|
749
|
+
</button>
|
750
|
+
</div>
|
751
|
+
);
|
752
|
+
}
|
753
|
+
```
|
278
754
|
|
279
|
-
|
755
|
+
## 🌍 Browser Compatibility
|
756
|
+
|
757
|
+
Frontend Hamroun works in all modern browsers:
|
758
|
+
|
759
|
+
<div class="browser-compatibility" style="display: flex; justify-content: space-between; margin: 20px 0;">
|
760
|
+
<div style="text-align: center; padding: 10px;">
|
761
|
+
<div style="font-size: 2em;">�Chrome</div>
|
762
|
+
<div>Latest 2 versions</div>
|
763
|
+
</div>
|
764
|
+
<div style="text-align: center; padding: 10px;">
|
765
|
+
<div style="font-size: 2em;">🦊</div>
|
766
|
+
<div>Firefox</div>
|
767
|
+
<div>Latest 2 versions</div>
|
768
|
+
</div>
|
769
|
+
<div style="text-align: center; padding: 10px;">
|
770
|
+
<div style="font-size: 2em;">🧭</div>
|
771
|
+
<div>Safari</div>
|
772
|
+
<div>Latest 2 versions</div>
|
773
|
+
</div>
|
774
|
+
<div style="text-align: center; padding: 10px;">
|
775
|
+
<div style="font-size: 2em;">🌐</div>
|
776
|
+
<div>Edge</div>
|
777
|
+
<div>Latest 2 versions</div>
|
778
|
+
</div>
|
779
|
+
<div style="text-align: center; padding: 10px;">
|
780
|
+
<div style="font-size: 2em;">🏛️</div>
|
781
|
+
<div>IE11</div>
|
782
|
+
<div>With polyfills</div>
|
783
|
+
</div>
|
784
|
+
</div>
|
785
|
+
|
786
|
+
## 👥 Contributing
|
787
|
+
|
788
|
+
Contributions are welcome! See [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for details.
|
789
|
+
|
790
|
+
<div class="contribution-workflow" style="background: #f8f9fa; border-radius: 8px; padding: 20px; margin: 20px 0;">
|
791
|
+
<h3>Contribution Workflow</h3>
|
792
|
+
<ol>
|
793
|
+
<li>Fork the repository</li>
|
794
|
+
<li>Create your feature branch: <code>git checkout -b feature/amazing-feature</code></li>
|
795
|
+
<li>Commit your changes: <code>git commit -m 'Add amazing feature'</code></li>
|
796
|
+
<li>Push to the branch: <code>git push origin feature/amazing-feature</code></li>
|
797
|
+
<li>Open a Pull Request</li>
|
798
|
+
</ol>
|
799
|
+
</div>
|
800
|
+
|
801
|
+
## 📚 Documentation
|
802
|
+
|
803
|
+
For complete documentation, visit [our documentation site](https://github.com/hamroun/frontend-hamroun).
|
804
|
+
|
805
|
+
<div align="center">
|
806
|
+
|
807
|
+
<div style="margin-top: 40px;">
|
808
|
+
<h3>💖 Support the Project</h3>
|
809
|
+
|
810
|
+
[](https://github.com/sponsors/hamroun)
|
811
|
+
[](https://github.com/hamroun/frontend-hamroun)
|
812
|
+
</div>
|
813
|
+
|
814
|
+
<div style="margin-top: 30px;">
|
815
|
+
<p>MIT © Hamroun</p>
|
816
|
+
</div>
|
817
|
+
|
818
|
+
</div>
|