Skip to content

Commit 3e2dd15

Browse files
authored
Merge pull request #19 from sdldev/copilot/analyze-asset-separation
Fix asset separation: implement auto-detection middleware for admin/site templates
2 parents e6c5633 + c634c1d commit 3e2dd15

9 files changed

Lines changed: 1139 additions & 0 deletions

File tree

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,22 @@ Project ini memiliki comprehensive Copilot instructions di `.github/copilot-inst
308308

309309
Instruksi ini memastikan Copilot menghasilkan code yang comply dengan semua standards.
310310

311+
### 📚 Asset Separation
312+
313+
Project ini menggunakan **pemisahan asset yang ketat** antara Admin dan Site:
314+
315+
- **Admin**: Entry point terpisah di `resources/js/entries/admin.tsx`
316+
- **Site**: Entry point terpisah di `resources/js/entries/site.tsx`
317+
- **Auto-detection**: Middleware otomatis memilih template berdasarkan route
318+
- **Optimized bundles**: Vite menghasilkan bundle terpisah untuk performa optimal
319+
320+
**Untuk detail lengkap**, lihat: [`docs/ASSET_SEPARATION.md`](docs/ASSET_SEPARATION.md)
321+
322+
**Verifikasi setup**:
323+
```bash
324+
bash scripts/verify-asset-separation.sh
325+
```
326+
311327
## 🎨 UI Components
312328

313329
Menggunakan **shadcn/ui** untuk component library yang:

app/Http/Middleware/HandleInertiaRequests.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@ class HandleInertiaRequests extends Middleware
1818
*/
1919
protected $rootView = 'app';
2020

21+
/**
22+
* Determine the current asset version.
23+
* Dynamically select the root view based on the request path.
24+
*
25+
* @return string
26+
*/
27+
public function rootView(Request $request): string
28+
{
29+
// Use admin template for admin routes
30+
if ($request->is('admin') || $request->is('admin/*')) {
31+
return 'admin/app';
32+
}
33+
34+
// Use site template for all other routes
35+
return 'site/app';
36+
}
37+
2138
/**
2239
* Determines the current asset version.
2340
*

docs/ASSET_SEPARATION.md

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
# Asset Separation: Admin Dashboard vs Site
2+
3+
> 📊 **Quick Visual Guide**: See [ASSET_SEPARATION_VISUAL.md](ASSET_SEPARATION_VISUAL.md) for diagrams and flowcharts.
4+
5+
## Ringkasan
6+
7+
Repository ini menggunakan pemisahan asset yang jelas antara **Admin Dashboard** dan **Site** (public/user-facing pages). Pemisahan ini mencakup:
8+
9+
1. **Entry Points terpisah** di Vite
10+
2. **Blade templates terpisah**
11+
3. **Route detection otomatis** melalui middleware
12+
4. **Page components terpisah** per namespace
13+
14+
## Diagram Alur
15+
16+
```
17+
Request (/admin/users)
18+
19+
HandleInertiaRequests Middleware
20+
21+
rootView() method
22+
23+
Is route 'admin' or 'admin/*'? → YES
24+
25+
Return 'admin/app'
26+
27+
Load: resources/views/admin/app.blade.php
28+
29+
@vite(['resources/js/entries/admin.tsx'])
30+
31+
Admin Entry Point:
32+
- Loads Toaster
33+
- Title: "Page - Admin - AppName"
34+
- Renders admin/* pages
35+
36+
Final Output: Admin Dashboard with admin.js bundle
37+
38+
39+
Request (/, /dashboard, /login, /settings/*)
40+
41+
HandleInertiaRequests Middleware
42+
43+
rootView() method
44+
45+
Is route 'admin' or 'admin/*'? → NO
46+
47+
Return 'site/app'
48+
49+
Load: resources/views/site/app.blade.php
50+
51+
@vite(['resources/js/entries/site.tsx'])
52+
53+
Site Entry Point:
54+
- No Toaster
55+
- Title: "Page - AppName"
56+
- Renders site/*, auth/*, settings/*, dashboard pages
57+
58+
Final Output: Site with site.js bundle
59+
```
60+
61+
## Struktur File
62+
63+
### Backend
64+
65+
```
66+
app/Http/Controllers/
67+
├── Admin/ # Controllers untuk admin dashboard
68+
│ ├── DashboardController.php
69+
│ ├── UserController.php
70+
│ └── ...
71+
└── Site/ # Controllers untuk public site
72+
└── HomeController.php
73+
74+
routes/
75+
├── admin.php # Admin routes (/admin/*)
76+
└── web.php # Site routes (/, /dashboard, /settings/*)
77+
```
78+
79+
### Frontend
80+
81+
```
82+
resources/
83+
├── views/
84+
│ ├── admin/
85+
│ │ └── app.blade.php # Admin template (loads admin.tsx)
86+
│ ├── site/
87+
│ │ └── app.blade.php # Site template (loads site.tsx)
88+
│ └── app.blade.php # [DEPRECATED] Legacy template
89+
90+
└── js/
91+
├── entries/
92+
│ ├── admin.tsx # Admin entry point
93+
│ ├── admin-ssr.tsx # Admin SSR entry
94+
│ ├── site.tsx # Site entry point
95+
│ └── site-ssr.tsx # Site SSR entry
96+
97+
└── pages/
98+
├── admin/ # Admin pages (dashboard, users, settings, etc)
99+
├── site/ # Site pages (home, etc)
100+
├── auth/ # Auth pages (login, register, etc) - uses site template
101+
├── settings/ # User settings - uses site template
102+
└── dashboard.tsx # User dashboard - uses site template
103+
```
104+
105+
## Cara Kerja
106+
107+
### 1. Vite Configuration
108+
109+
File `vite.config.ts` mendefinisikan dua entry points terpisah:
110+
111+
```typescript
112+
laravel({
113+
input: [
114+
'resources/js/entries/admin.tsx',
115+
'resources/js/entries/site.tsx',
116+
],
117+
ssr: [
118+
'resources/js/entries/admin-ssr.tsx',
119+
'resources/js/entries/site-ssr.tsx',
120+
],
121+
})
122+
```
123+
124+
### 2. Middleware: Root View Selection
125+
126+
`HandleInertiaRequests` middleware secara otomatis mendeteksi route dan memilih template yang sesuai:
127+
128+
```php
129+
public function rootView(Request $request): string
130+
{
131+
// Admin routes: /admin atau /admin/*
132+
if ($request->is('admin') || $request->is('admin/*')) {
133+
return 'admin/app';
134+
}
135+
136+
// Semua route lainnya menggunakan site template
137+
return 'site/app';
138+
}
139+
```
140+
141+
### 3. Blade Templates
142+
143+
**Admin Template** (`resources/views/admin/app.blade.php`):
144+
```blade
145+
@vite(['resources/js/entries/admin.tsx', "resources/js/pages/{$page['component']}.tsx"])
146+
```
147+
148+
**Site Template** (`resources/views/site/app.blade.php`):
149+
```blade
150+
@vite(['resources/js/entries/site.tsx', "resources/js/pages/{$page['component']}.tsx"])
151+
```
152+
153+
### 4. Entry Points
154+
155+
**Admin Entry** (`resources/js/entries/admin.tsx`):
156+
- Includes `Toaster` component for notifications
157+
- Title format: `"${title} - Admin - ${appName}"`
158+
- Initializes admin-specific features
159+
160+
**Site Entry** (`resources/js/entries/site.tsx`):
161+
- Simpler, no Toaster
162+
- Title format: `"${title} - ${appName}"`
163+
- Focused on public/user features
164+
165+
## Route Mapping
166+
167+
| Route Pattern | Template | Entry Point | Page Namespace |
168+
|--------------|----------|-------------|----------------|
169+
| `/admin/*` | `admin/app` | `admin.tsx` | `admin/*` |
170+
| `/` | `site/app` | `site.tsx` | `site/home` |
171+
| `/dashboard` | `site/app` | `site.tsx` | `dashboard` |
172+
| `/settings/*` | `site/app` | `site.tsx` | `settings/*` |
173+
| `/login`, `/register`, etc | `site/app` | `site.tsx` | `auth/*` |
174+
175+
## Build Output
176+
177+
Ketika menjalankan `npm run build`, Vite akan menghasilkan bundle terpisah:
178+
179+
```
180+
public/build/
181+
├── assets/
182+
│ ├── admin-[hash].js # Admin bundle
183+
│ ├── site-[hash].js # Site bundle
184+
│ ├── vendor-[hash].js # Shared vendor code (React, dll)
185+
│ └── ...
186+
└── manifest.json
187+
```
188+
189+
### Code Splitting Benefits
190+
191+
1. **Smaller Initial Load**: User site tidak perlu download admin code
192+
2. **Better Caching**: Admin updates tidak mempengaruhi site bundle
193+
3. **Parallel Loading**: Browser bisa download chunks secara parallel
194+
4. **Optimized Chunks**: Vendor code (React, Inertia) di-share antar bundles
195+
196+
## Verifikasi Build Output
197+
198+
Untuk memastikan pemisahan asset berfungsi dengan baik:
199+
200+
### 1. Development Mode
201+
202+
```bash
203+
npm run dev
204+
```
205+
206+
Akses halaman dan periksa di browser DevTools:
207+
- **Admin pages** (`/admin/dashboard`): Harus load `admin.tsx` entry
208+
- **Site pages** (`/`, `/dashboard`): Harus load `site.tsx` entry
209+
210+
### 2. Production Build
211+
212+
```bash
213+
npm run build
214+
```
215+
216+
Output yang diharapkan:
217+
```
218+
public/build/assets/
219+
├── admin-[hash].js # Admin bundle (~200-300KB)
220+
├── site-[hash].js # Site bundle (~150-200KB)
221+
├── vendor-[hash].js # Shared vendors (React, Inertia)
222+
├── ui-[hash].js # Shared UI components (Radix)
223+
└── [page-specific].js # Code-split pages
224+
```
225+
226+
### 3. Bundle Analysis
227+
228+
Untuk menganalisis ukuran bundle:
229+
230+
```bash
231+
# Install analyzer
232+
npm install --save-dev rollup-plugin-visualizer
233+
234+
# Build dengan analisis (add to vite.config.ts)
235+
# visualizer({ open: true })
236+
237+
npm run build
238+
```
239+
240+
## Testing
241+
242+
Test suite memverifikasi bahwa pemisahan asset berfungsi dengan benar:
243+
244+
```bash
245+
php artisan test --filter AssetSeparationTest
246+
```
247+
248+
Tests mencakup:
249+
- ✅ Admin routes load admin template
250+
- ✅ Site routes load site template
251+
- ✅ Middleware correctly determines root view
252+
- ✅ Each route type uses correct entry point
253+
254+
## Menambahkan Feature Baru
255+
256+
### Admin Feature
257+
258+
1. **Controller**: `app/Http/Controllers/Admin/NewFeatureController.php`
259+
2. **Route**: Tambahkan di `routes/admin.php`
260+
3. **Page**: Buat di `resources/js/pages/admin/new-feature/Index.tsx`
261+
4. **Automatic**: Middleware akan otomatis load `admin/app` template
262+
263+
### Site Feature
264+
265+
1. **Controller**: `app/Http/Controllers/Site/NewFeatureController.php`
266+
2. **Route**: Tambahkan di `routes/web.php`
267+
3. **Page**: Buat di `resources/js/pages/site/new-feature.tsx`
268+
4. **Automatic**: Middleware akan otomatis load `site/app` template
269+
270+
## Troubleshooting
271+
272+
### Issue: Wrong template loaded
273+
274+
**Solusi**: Periksa route pattern di middleware. Admin routes harus mulai dengan `/admin`.
275+
276+
### Issue: Asset tidak terload
277+
278+
**Solusi**:
279+
1. Pastikan blade template menggunakan `@vite()` directive yang benar
280+
2. Jalankan `npm run build` untuk production
281+
3. Jalankan `npm run dev` untuk development
282+
283+
### Issue: Code dari admin muncul di site
284+
285+
**Solusi**: Pastikan import statement tidak cross-reference antar namespace.
286+
287+
## Kesimpulan
288+
289+
Pemisahan asset antara admin dan site **sudah berjalan dengan baik** dengan struktur yang solid:
290+
291+
**Separation of Concerns**: Admin dan Site code terpisah jelas
292+
**Automatic Detection**: Middleware otomatis pilih template yang tepat
293+
**Optimized Bundling**: Vite menghasilkan bundles terpisah dan efisien
294+
**Maintainable**: Struktur jelas dan mudah di-maintain
295+
**Tested**: Test suite memverifikasi fungsi pemisahan
296+
297+
Implementasi ini mengikuti best practices Laravel + Inertia + Vite untuk multi-entry point applications.

0 commit comments

Comments
 (0)