Skip to content

Full-Stack Development

Introduction

Full-stack development encompasses the complete technology stack from frontend user interfaces to backend services, databases, and API design. This article surveys the core technologies and best practices in modern full-stack development.


1. Full-Stack Architecture Overview

graph TB
    subgraph Frontend
        A[Browser/Client]
        A1[React / Vue]
        A2[HTML/CSS/JS]
    end

    subgraph API Layer
        B[API Gateway / Reverse Proxy]
        B1[RESTful API / GraphQL]
    end

    subgraph Backend
        C1[Flask / FastAPI]
        C2[Spring Boot]
        C3[Business Logic Layer]
    end

    subgraph Data Layer
        D1[(PostgreSQL)]
        D2[(MongoDB)]
        D3[(Redis Cache)]
    end

    A --> A1 --> A2
    A2 -->|HTTP/WebSocket| B
    B --> B1
    B1 --> C1
    B1 --> C2
    C1 --> C3
    C2 --> C3
    C3 --> D1
    C3 --> D2
    C3 --> D3

2. Frontend Frameworks

2.1 React

React is a UI library developed by Facebook, with core principles: componentization + declarative + unidirectional data flow.

Function Components and Hooks:

import { useState, useEffect, useCallback } from 'react';

function UserList() {
    const [users, setUsers] = useState([]);
    const [loading, setLoading] = useState(true);
    const [search, setSearch] = useState('');

    useEffect(() => {
        // Side effect: fetch data
        fetch('/api/users')
            .then(res => res.json())
            .then(data => {
                setUsers(data);
                setLoading(false);
            });
    }, []);  // empty dependency = runs only on mount

    const filteredUsers = users.filter(u => 
        u.name.toLowerCase().includes(search.toLowerCase())
    );

    if (loading) return <div>Loading...</div>;

    return (
        <div>
            <input 
                value={search} 
                onChange={e => setSearch(e.target.value)}
                placeholder="Search users..."
            />
            <ul>
                {filteredUsers.map(user => (
                    <UserCard key={user.id} user={user} />
                ))}
            </ul>
        </div>
    );
}

function UserCard({ user }) {
    return (
        <li className="user-card">
            <h3>{user.name}</h3>
            <p>{user.email}</p>
        </li>
    );
}

Common Hooks:

Hook Purpose
useState State management
useEffect Side effects (data fetching, subscriptions)
useContext Cross-component state sharing
useReducer Complex state logic
useMemo Memoize computed results
useCallback Memoize function references
useRef DOM references / mutable values

State Management:

  • Context API: simple global state
  • Redux / Zustand: complex state management
  • React Query / SWR: server state management

2.2 Vue (Composition API)

<script setup>
import { ref, computed, onMounted } from 'vue';

const users = ref([]);
const search = ref('');

const filteredUsers = computed(() =>
    users.value.filter(u => 
        u.name.toLowerCase().includes(search.value.toLowerCase())
    )
);

onMounted(async () => {
    const res = await fetch('/api/users');
    users.value = await res.json();
});
</script>

<template>
    <input v-model="search" placeholder="Search..." />
    <ul>
        <li v-for="user in filteredUsers" :key="user.id">
            {{ user.name }} - {{ user.email }}
        </li>
    </ul>
</template>

2.3 React vs Vue

Dimension React Vue
Templates JSX (HTML in JS) Template (logic in HTML)
Reactivity Manual setState Automatic dependency tracking
Ecosystem Rich but fragmented Officially unified (Router, Pinia)
Learning curve Medium Lower
Use cases Large complex applications Small-to-medium apps, rapid development

3. Backend Frameworks

3.1 Flask (Python Micro-Framework)

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/users', methods=['GET'])
def get_users():
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    users = User.query.paginate(page=page, per_page=per_page)
    return jsonify({
        'users': [u.to_dict() for u in users.items],
        'total': users.total,
        'pages': users.pages
    })

@app.route('/api/users', methods=['POST'])
def create_user():
    data = request.get_json()
    user = User(name=data['name'], email=data['email'])
    db.session.add(user)
    db.session.commit()
    return jsonify(user.to_dict()), 201

3.2 FastAPI (Modern Python Framework)

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, EmailStr
from typing import Optional

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    email: EmailStr
    age: Optional[int] = None

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.get("/api/users", response_model=list[UserResponse])
async def get_users(skip: int = 0, limit: int = 20):
    return await User.find_all(skip=skip, limit=limit)

@app.post("/api/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
    # Pydantic automatically validates the request body
    db_user = await User.find_by_email(user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return await User.create(**user.dict())

FastAPI advantages:

  • Automatic API documentation (Swagger UI + ReDoc)
  • Type validation based on Pydantic
  • Native async/await support
  • Performance comparable to Go/Node.js

3.3 Spring Boot (Java)

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public ResponseEntity<Page<UserDTO>> getUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        return ResponseEntity.ok(userService.findAll(PageRequest.of(page, size)));
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(@Valid @RequestBody CreateUserRequest request) {
        UserDTO user = userService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
}

4. RESTful API Design

4.1 HTTP Methods

Method Semantics Idempotent Example
GET Read resource Yes GET /api/users/123
POST Create resource No POST /api/users
PUT Full update Yes PUT /api/users/123
PATCH Partial update Yes PATCH /api/users/123
DELETE Delete resource Yes DELETE /api/users/123

4.2 Status Codes

Range Meaning Common Codes
2xx Success 200 OK, 201 Created, 204 No Content
3xx Redirect 301 Moved, 304 Not Modified
4xx Client error 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests
5xx Server error 500 Internal Error, 502 Bad Gateway, 503 Unavailable

4.3 API Versioning

# URL path versioning (most common)
GET /api/v1/users
GET /api/v2/users

# Header versioning
GET /api/users
Accept: application/vnd.myapp.v2+json

# Query parameter versioning
GET /api/users?version=2

4.4 Pagination, Filtering, and Sorting

GET /api/users?page=2&per_page=20
GET /api/users?age_gte=18&status=active
GET /api/users?sort=-created_at,name

Response:
{
    "data": [...],
    "meta": {
        "total": 150,
        "page": 2,
        "per_page": 20,
        "pages": 8
    }
}

5. Authentication and Authorization

5.1 JWT (JSON Web Token)

Header.Payload.Signature

Header:  {"alg": "HS256", "typ": "JWT"}
Payload: {"sub": "user123", "exp": 1700000000, "role": "admin"}
Signature: HMACSHA256(base64(header) + "." + base64(payload), secret)
# FastAPI JWT example
from jose import jwt
from datetime import datetime, timedelta

SECRET_KEY = "your-secret-key"

def create_access_token(data: dict, expires_delta: timedelta = timedelta(hours=1)):
    to_encode = data.copy()
    to_encode["exp"] = datetime.utcnow() + expires_delta
    return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")

def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        user_id = payload.get("sub")
        if user_id is None:
            raise HTTPException(status_code=401)
        return user_id
    except jwt.JWTError:
        raise HTTPException(status_code=401)

5.2 OAuth 2.0

User → App → Authorization Server (Google/GitHub)
                    │
                    ▼ Authorization Code
User ← App ← Authorization Server
                    │
                    ▼ Access Token
              Resource Server → Returns user data

Four grant types:

Grant Type Use Case
Authorization Code Web applications (most secure)
PKCE Single-page apps / mobile
Client Credentials Service-to-service communication
Device Code IoT / browserless devices

6. Databases

6.1 SQL (PostgreSQL)

-- Table design
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_posts_user_id ON posts(user_id);

-- Query: JOIN + aggregation
SELECT u.name, COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.id, u.name
HAVING COUNT(p.id) > 5
ORDER BY post_count DESC;

6.2 NoSQL (MongoDB)

// Document model: flexible schema
db.users.insertOne({
    name: "Alice",
    email: "alice@example.com",
    profile: {
        bio: "Developer",
        skills: ["Python", "React", "MongoDB"]
    },
    posts: [
        { title: "Hello World", date: ISODate("2024-01-01") }
    ]
});

// Aggregation pipeline
db.orders.aggregate([
    { $match: { status: "completed" } },
    { $group: { _id: "$user_id", total: { $sum: "$amount" } } },
    { $sort: { total: -1 } },
    { $limit: 10 }
]);

6.3 SQL vs NoSQL

Dimension SQL (PostgreSQL) NoSQL (MongoDB)
Data model Relational tables Document/Key-value/Graph
Schema Fixed (requires migration) Flexible
Transactions Full ACID Limited support
Scaling Primarily vertical Primarily horizontal
Use cases Complex queries, data consistency Rapid iteration, large-scale data

7. Development Tools and Practices

Tool Type Recommendations
API testing Postman, httpie, curl
API documentation Swagger/OpenAPI, Redoc
Database migration Alembic (Python), Flyway (Java)
ORM SQLAlchemy, Django ORM, Prisma
Frontend build Vite, Webpack, esbuild
Full-stack frameworks Next.js, Nuxt.js, Django

Relations to Other Topics

  • See System Design for how APIs, caching, databases, and frontend/backend boundaries compose into a whole system
  • See Database Systems for how relational and NoSQL storage choices support the application layer
  • See Version Control and CI/CD for the build, test, and deployment workflow of full-stack projects
  • See Testing and Quality Assurance for how unit, integration, and end-to-end testing cooperate across layers

References

  • React Official Documentation: https://react.dev
  • Vue Official Documentation: https://vuejs.org
  • FastAPI Official Documentation: https://fastapi.tiangolo.com
  • "RESTful Web APIs" - Leonard Richardson

评论 #