Frontend Development Skills
HTML5 Fundamentals
<!-- Semantic markup -->
<header><nav></nav></header>
<main>
<article><h1>Title</h1><p>Content</p></article>
</main>
<footer></footer>
<!-- Accessibility -->
<img alt="descriptive text" src="image.jpg">
<button aria-label="Close">×</button>
<label for="email">Email:</label>
<input id="email" type="email">
CSS3 Modern Layouts
/* Flexbox */
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}
/* Grid */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
/* Responsive */
@media (max-width: 768px) {
.grid { grid-template-columns: 1fr; }
}
JavaScript ES6+ Essentials
// Arrow functions
const add = (a, b) => a + b;
// Destructuring
const {name, age} = user;
const [first, ...rest] = array;
// Async/await with error handling
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Fetch failed:', error);
throw error;
}
}
// Array methods
arr.map(x => x * 2)
.filter(x => x > 5)
.reduce((acc, x) => acc + x, 0);
React Hooks Pattern
import {useState, useEffect, useCallback} from 'react';
function Counter() {
const [count, setCount] = useState(0);
const [error, setError] = useState(null);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
const increment = useCallback(() => {
setCount(prev => prev + 1);
}, []);
if (error) return <ErrorBoundary error={error} />;
return (
<button onClick={increment}>
Count: {count}
</button>
);
}
State Management
// Context API with TypeScript
interface UserContextType {
user: User | null;
setUser: (user: User) => void;
}
const UserContext = createContext<UserContextType | undefined>(undefined);
export function useUser() {
const context = useContext(UserContext);
if (!context) {
throw new Error('useUser must be within UserProvider');
}
return context;
}
Performance Optimization
// Code splitting
const LazyComponent = lazy(() => import('./Component'));
// Memoization
const MemoizedComponent = memo(Component);
const value = useMemo(() => expensiveComputation(), [deps]);
// useCallback for stable references
const handleClick = useCallback(() => {
// handler
}, [dependencies]);
Web Performance Metrics
| Metric |
Target |
Description |
| LCP |
< 2.5s |
Largest Contentful Paint |
| FID |
< 100ms |
First Input Delay |
| CLS |
< 0.1 |
Cumulative Layout Shift |
| TTI |
< 5s |
Time to Interactive |
| FCP |
< 1.8s |
First Contentful Paint |
Accessibility Standards
- WCAG 2.1 Level AA compliance
- Keyboard navigation support
- Screen reader compatibility
- Color contrast ratios (4.5:1 minimum)
- Semantic HTML structure
Unit Test Template
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('Counter Component', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('increments count on click', async () => {
render(<Counter />);
const button = screen.getByRole('button');
await userEvent.click(button);
expect(screen.getByText(/Count: 1/)).toBeInTheDocument();
});
test('handles error state', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
render(<Counter initialError={new Error('Test')} />);
expect(screen.getByRole('alert')).toBeInTheDocument();
});
});
Troubleshooting Guide
| Symptom |
Cause |
Solution |
| Component not updating |
Stale closure |
Use functional setState |
| Infinite re-render |
useEffect missing deps |
Add all dependencies |
| Memory leak warning |
Unmounted state update |
Use cleanup function |
| Hydration mismatch |
Server/client diff |
Use useEffect for client-only |
Key Concepts Checklist
Source: https://roadmap.sh
Version: 2.0.0
Last Updated: 2025-01-01