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

|
7
|
-

|
8
|
-

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