name: Frontend Development description: พัฒนา Frontend ด้วย Angular, React, Vue, Next.js อย่างมืออาชีพ
Frontend Development Skill
Overview
Skill สำหรับพัฒนา Frontend applications ครอบคลุม 4 frameworks หลัก พร้อม best practices
Angular
Project Structure
src/
├── app/
│ ├── core/ # Singleton services, guards, interceptors
│ │ ├── services/
│ │ ├── guards/
│ │ └── interceptors/
│ ├── shared/ # Shared components, pipes, directives
│ │ ├── components/
│ │ ├── pipes/
│ │ └── directives/
│ ├── features/ # Feature modules
│ │ ├── auth/
│ │ ├── dashboard/
│ │ └── users/
│ └── app.component.ts
├── assets/
└── environments/
Best Practices
- Standalone Components - ใช้ standalone components (Angular 15+)
- Signals - ใช้ Signals สำหรับ reactivity (Angular 16+)
- Smart vs Dumb Components - แยก container และ presentational
- OnPush Change Detection - ใช้เพื่อ performance
- Lazy Loading - Load modules ตามต้องการ
Common Patterns
// Standalone Component with Signals (Angular 17+)
import { toSignal } from "@angular/core/rxjs-interop";
@Component({
selector: "app-user-list",
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@for (user of users(); track user.id) {
<div>{{ user.name }}</div>
}
`,
})
export class UserListComponent {
private userService = inject(UserService);
// ใช้ toSignal() แทน effect() + subscribe
users = toSignal(this.userService.getUsers(), { initialValue: [] });
}
React
Project Structure
src/
├── components/ # Shared/reusable components
│ ├── ui/ # Basic UI components
│ └── layout/ # Layout components
├── features/ # Feature-based modules
│ ├── auth/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── api.ts
│ └── users/
├── hooks/ # Shared custom hooks
├── lib/ # Utilities, helpers
├── services/ # API services
└── stores/ # State management (Zustand/Redux)
Best Practices
- Functional Components - ใช้ functional components เสมอ
- Custom Hooks - Extract logic ออกเป็น hooks
- React Query/SWR - สำหรับ data fetching
- Zustand/Jotai - สำหรับ simple state management
- Error Boundaries - Handle errors gracefully
Common Patterns
// Custom Hook Pattern
function useUsers() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetchUsers()
.then(setUsers)
.catch(setError)
.finally(() => setLoading(false));
}, []);
return { users, loading, error };
}
// React Query Pattern
function useUsers() {
return useQuery({
queryKey: ["users"],
queryFn: fetchUsers,
staleTime: 5 * 60 * 1000,
});
}
Vue 3
Project Structure
src/
├── components/ # Shared components
│ ├── ui/
│ └── layout/
├── composables/ # Composition API functions
├── views/ # Page components
├── stores/ # Pinia stores
├── services/ # API services
├── router/
└── assets/
Best Practices
- Composition API - ใช้
<script setup>syntax - Pinia - สำหรับ state management
- Composables - Extract reusable logic
- defineProps/defineEmits - Type-safe props and events
- Suspense - สำหรับ async components
Common Patterns
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { useUserStore } from "@/stores/user";
// Props & Emits
const props = defineProps<{
userId: number;
}>();
const emit = defineEmits<{
(e: "select", user: User): void;
}>();
// Composables
const userStore = useUserStore();
// Reactive State
const searchQuery = ref("");
// Computed
const filteredUsers = computed(() =>
userStore.users.filter((u) => u.name.includes(searchQuery.value)),
);
// Lifecycle
onMounted(() => {
userStore.fetchUsers();
});
</script>
Next.js (App Router)
Project Structure
src/
├── app/ # App Router
│ ├── (auth)/ # Route groups
│ │ ├── login/
│ │ └── register/
│ ├── dashboard/
│ │ ├── page.tsx
│ │ ├── layout.tsx
│ │ └── loading.tsx
│ ├── api/ # API Routes
│ │ └── users/
│ ├── layout.tsx
│ └── page.tsx
├── components/
│ ├── ui/
│ └── features/
├── lib/ # Utilities
└── services/ # API services
Best Practices
- Server Components - Default, ใช้สำหรับ data fetching
- Client Components - เฉพาะเมื่อต้องการ interactivity
- Route Groups - จัดกลุ่ม routes
- Parallel Routes - Render multiple pages
- Server Actions - สำหรับ form submissions
Common Patterns
// Server Component (default)
async function UsersPage() {
const users = await fetchUsers(); // Server-side
return (
<div>
<UserList users={users} />
<AddUserButton /> {/* Client Component */}
</div>
);
}
// Client Component
("use client");
function AddUserButton() {
const [open, setOpen] = useState(false);
return <button onClick={() => setOpen(true)}>Add User</button>;
}
// Server Action
async function createUser(formData: FormData) {
"use server";
const name = formData.get("name");
await db.users.create({ name });
revalidatePath("/users");
}
Shared Best Practices
CSS/Styling
- CSS Modules หรือ Tailwind CSS
- CSS Variables สำหรับ theming
- Mobile-first responsive design
- Consistent spacing (8px grid system)
Performance
- Lazy loading components และ routes
- Image optimization (next/image, @angular/common)
- Code splitting
- Memoization (useMemo, React.memo, computed)
Accessibility
- Semantic HTML
- ARIA labels
- Keyboard navigation
- Color contrast
- Focus management
Frontend Checklist
- ใช้ TypeScript
- Folder structure ที่เหมาะสม
- Component composition ที่ดี
- State management ที่เหมาะสม
- Error handling
- Loading states
- Responsive design
- Accessibility
- Performance optimization
- Testing coverage