404 Not Found

404 Not Found


nginx

Project Design

Completamos todo o material das Fases 1-4. Charlie agora vai integrar todo esse conhecimento para projetar uma plataforma e-commerce MegaShop completa. Da análise de requisitos ao design de arquitetura, e dos modelos de dados às especificações de API, este é o primeiro passo no projeto prático.

1. O Que Você Vai Aprender


2. Uma História Real de um Arquiteto

(1) Dor: Desenvolvimento Sem Design

Charlie havia instruído a equipe a começar a escrever código imediatamente sem nenhuma documentação de design. Como resultado, a estrutura de dados do carrinho de compras de Alice não correspondia aos dados de pedido de Bob, a nomenclatura da API era caótica, o banco de dados não tinha índices, as consultas eram lentas, e o custo de fazer alterações depois era enorme.

(2) Soluções de Design de Sistema

Design Primeiro, Depois Desenvolver—Use diagramas ER para definir o modelo de dados, especificações RESTful para definir a API, e diagramas de arquitetura para definir os limites do sistema. Gaste uma semana extra na fase de design e economize três semanas durante o desenvolvimento.

(3) Benefícios: Um Roteiro Claro

Quando cada desenvolvedor se refere ao mesmo documento de design—com estruturas de dados consistentes, especificações de API unificadas e limites arquiteturais claros—a eficiência da colaboração triplica.


3. Análise de Requisitos

(1) Funções de Usuário e Necessidades Centrais

Função Identidade Necessidades Centrais Métricas Chave
Alice Consumidora Navegar/Buscar/Adicionar ao Carrinho/Checkout/Avaliar First Screen < 2s, Busca < 500ms
Bob Administrador Gerenciamento de Produtos/Processamento de Pedidos/Gerenciamento de Usuários Resposta CRUD < 200 ms
Charlie Arquiteto Estabilidade do Sistema/Alta Performance/Escalabilidade 99.9% disponibilidade, suporta 1 milhão de produtos

(2) Divisão de Módulos Funcionais

Módulo Função Prioridade Páginas Afetadas
Autenticação Cadastro/Login/OAuth2/JWT P0 /login, /register
Produto CRUD/Busca/Categorias/Filtros P0 /products, /products/[id]
Carrinho de Compras Adicionar/Trocar Quantidade/Remover/Limpar P0 /cart
Pedido Criar/Pagar/Verificar Status P0 /checkout, /orders
Usuário Informações Pessoais/Endereço/Avaliações P1 /profile
Administração CRUD do Painel/Estatísticas/Moderação P1 /admin/**
Internacionalização Chinês/Inglês/Japonês + Múltiplas Moedas P1 Global
SEO meta dinâmico/Sitemap/JSON-LD P0 Página de Produto

4. Design de Arquitetura

(1) Visão Geral da Arquitetura do Sistema MegaShop

100%
graph TB
    subgraph Client["Camada Client"]
        Browser[Navegador / Mobile]
        Bot[Bot de Mecanismo de Busca]
    end

    subgraph CDN["Camada CDN"]
        CF[Cloudflare / Vercel Edge]
    end

    subgraph Nuxt["Aplicação Nuxt 3"]
        SSR[Motor SSR]
        ISR[Cache ISR]
        API[Rotas Nitro API]
        MW[Middleware / Auth]
    end

    subgraph Data["Camada de Dados"]
        PG[(PostgreSQL)]
        Redis[(Cache Redis)]
        S3[Armazenamento de Objetos / Imagens]
    end

    subgraph External["Serviços Externos"]
        Stripe[Pagamento Stripe]
        Google[Google OAuth2]
        Analytics[Serviço de Analytics]
    end

    Browser --> CDN
    Bot --> CDN
    CDN --> SSR
    CDN --> ISR
    SSR --> API
    API --> MW
    API --> PG
    API --> Redis
    API --> S3
    API --> Stripe
    API --> Google
    API --> Analytics
    ISR --> Redis

(2) Design de Estratégia de Renderização

Tipo de Página Modo de Renderização swr Motivo
Home SSG - Conteúdo Estável
Lista de Produtos ISR 3600s Atualizado a cada hora
Detalhes do Produto ISR 86400s Atualizado diariamente
Resultados de Busca SSR - Consulta em tempo real
Carrinho/Checkout CSR - Apenas para membros
Painel Admin CSR - SEO não necessário
Rotas de API Dinâmico - Cache sob demanda

(3) Seleção do Stack Tecnológico

(1) ▶ Exemplo: Integração do Stack Tecnológico no nuxt.config.ts

TYPESCRIPT
// nuxt.config.ts - Integração completa do stack tecnológico
export default defineNuxtConfig({
  ssr: true,
  modules: [
    '@pinia/nuxt',
    '@nuxtjs/tailwindcss',
    '@nuxtjs/i18n',
    '@nuxtjs/sitemap',
    '@nuxt/image',
    '~/modules/analytics'
  ],
  i18n: {
    locales: [
      { code: 'en', name: 'English', file: 'en.json', currency: 'USD' },
      { code: 'zh', name: 'Chinese', file: 'zh.json', currency: 'CNY' },
      { code: 'ja', name: 'Japanese', file: 'ja.json', currency: 'JPY' }
    ],
    defaultLocale: 'en',
    lazy: true,
    langDir: 'locales/'
  },
  image: { quality: 80, format: ['webp', 'avif'] }
})

Saída:

TEXT
// Execução bem-sucedida

(2) ▶ Exemplo: Orquestração de Serviços Docker Compose

YAML
# docker-compose.yml - Definição de infraestrutura
services:
  web:
    build: .
    ports: ["3000:3000"]
    depends_on: [db, redis]
  db:
    image: postgres:16-alpine
    volumes: [postgres_data:/var/lib/postgresql/data]
  redis:
    image: redis:7-alpine
    volumes: [redis_data:/data]
  nginx:
    image: nginx:alpine
    ports: ["80:80", "443:443"]
    depends_on: [web]

Saída:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp
Nível Tecnologia Motivo da Escolha
Framework Nuxt 3 Renderização Híbrida SSR/ISR/CSR
UI Vue 3 + TailwindCSS Reativo + Desenvolvimento Rápido
Gerenciamento de Estado Pinia Solução Oficial Vue 3 + Suporte SSR
Banco de Dados PostgreSQL + Prisma ORM Type-safe + Milhões de Consultas
Cache Redis + Nitro KV Cache de API + Armazenamento ISR
Autenticação JWT + OAuth2 Stateless + Login Social
Internacionalização @nuxtjs/i18n Multilíngue + SEO hreflang
Imagem @nuxt/image WebP/AVIF + Responsivo
Testes Vitest + Playwright Unitário + E2E
Implantação Docker Compose Orquestração de Serviços Full-Stack
CI/CD GitHub Actions Pipelines Automatizados

5. Design de Modelo de Dados

(1) Diagrama ER

100%
erDiagram
    User ||--o{ Order : "faz"
    User ||--o{ Review : "escreve"
    User ||--o{ CartItem : "tem"
    User ||--o{ Address : "possui"
    Product ||--o{ OrderItem : "incluído em"
    Product ||--o{ CartItem : "adicionado ao"
    Product ||--o{ Review : "recebe"
    Product ||--o{ ProductImage : "tem"
    Product }o--|| Category : "pertence a"
    Category ||--o{ Category : "pai-filho"
    Order ||--o{ OrderItem : "contém"
    Order }o--|| Address : "envia para"

(2) Design de Tabelas Centrais

(1) ▶ Exemplo: Schema Prisma Central

PRISMA
// Modelos-chave do prisma/schema.prisma
model Product {
  id          Int       @id @default(autoincrement())
  name        String
  slug        String    @unique
  price       Decimal   @db.Decimal(10, 2)
  inStock     Boolean   @default(true)
  categoryId  Int
  category    Category  @relation(fields: [categoryId], references: [id])
  orderItems  OrderItem[]
  cartItems   CartItem[]
  @@index([categoryId])
  @@index([price])
}

model Order {
  id        Int       @id @default(autoincrement())
  userId    Int
  user      User      @relation(fields: [userId], references: [id])
  total     Decimal   @db.Decimal(10, 2)
  status    OrderStatus @default(PENDING)
  items     OrderItem[]
  @@index([userId])
  @@index([status])
}

Saída:

TEXT
// Execução bem-sucedida

(2) ▶ Exemplo: Definições de Códigos de Erro da API

TYPESCRIPT
// server/utils/errors.ts
export const ErrorCodes = {
  VALIDATION_ERROR: { statusCode: 400, message: 'Validation error' },
  AUTH_REQUIRED: { statusCode: 401, message: 'Authentication required' },
  TOKEN_EXPIRED: { statusCode: 401, message: 'Token expired' },
  FORBIDDEN: { statusCode: 403, message: 'Insufficient permissions' },
  NOT_FOUND: { statusCode: 404, message: 'Resource not found' },
  CONFLICT: { statusCode: 409, message: 'Resource conflict' },
  RATE_LIMITED: { statusCode: 429, message: 'Too many requests' }
} as const

export function throwError(code: keyof typeof ErrorCodes, details?: any) {
  const err = ErrorCodes[code]
  throw createError({ statusCode: err.statusCode, message: err.message, data: { errorCode: code, details } })
}

Saída:

TEXT
// Execução bem-sucedida

(3) ▶ Exemplo: Formato Padrão de Resposta da API

TYPESCRIPT
// server/utils/response.ts
export function successResponse(data: any, message = 'Success') {
  return { data, message, timestamp: Date.now() }
}

export function listResponse(items: any[], total: number, page: number, limit: number) {
  return { items, total, page, limit, timestamp: Date.now() }
}

export function errorResponse(statusCode: number, errorCode: string, message: string, details?: any) {
  return { statusCode, errorCode, message, details, timestamp: Date.now() }
}

Saída:

TEXT
// Execução bem-sucedida

(4) ▶ Exemplo: Configuração de estratégia de renderização routeRules

TYPESCRIPT
// nuxt.config.ts - Estratégia de renderização por rota
routeRules: {
  '/': { prerender: true },
  '/products': { swr: 3600 },
  '/products/**': { swr: 86400 },
  '/admin/**': { ssr: false },
  '/cart': { ssr: false },
  '/api/**': { cors: true },
  '/_nuxt/**': { headers: { 'cache-control': 'public, max-age=31536000, immutable' } }
}

Saída:

TEXT
// Execução bem-sucedida

(5) ▶ Exemplo: Estrutura do Pipeline CI/CD

YAML
# .github/workflows/ci.yml - Pipeline principal
name: CI
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps: [{ uses: actions/checkout@v4 }, { run: npm ci }, { run: npm run lint }]
  test:
    needs: lint
    steps: [{ run: npm run test:coverage }]
  build:
    needs: test
    steps: [{ run: npm run build }]

Saída:

TEXT
CI/CD pipeline loaded
Pipeline status: passed
Tests: 12 passed, 0 failed
Tabela Número de Campos Índice Principal Volume Estimado de Dados
Product 12 slug, categoryId, price 1 milhão
Category 6 slug, parentId 500
User 10 email, role 500.000
Order 8 userId, status, createdAt 1 milhão
OrderItem 6 orderId, productId 5 milhões
CartItem 5 userId+productId (unique) 100.000
Review 7 productId, userId 2 milhões
Address 8 userId 500 mil

6. Especificações de API

(1) Design RESTful API

Método Path Descrição Autenticação
GET /api/products Lista de Produtos (Paginação/Filtros) Nenhuma
GET /api/products/:id Detalhes do Produto Nenhuma
POST /api/products Criar Produto Admin
PUT /api/products/:id Atualizar Produto Admin
DELETE /api/products/:id Excluir Produto Admin
GET /api/categories Lista de Categorias Nenhuma
POST /api/auth/register Registro Nenhuma
POST /api/auth/login Login Nenhuma
POST /api/auth/refresh Renovar Token Cookie
GET /api/cart Carrinho de Compras Usuário
POST /api/cart/add Adicionar ao Carrinho Usuário
DELETE /api/cart/remove Remover Usuário
POST /api/orders Criar Pedido Usuário
GET /api/orders Lista de Pedidos Usuário
GET /api/orders/:id Detalhes do Pedido Usuário

(2) Especificações de Códigos de Erro

Status Code Código de Erro Descrição
400 VALIDATION_ERROR Validação de parâmetros da requisição falhou
401 AUTH_REQUIRED Não logado
401 TOKEN_EXPIRED Token expirado
403 FORBIDDEN Permissões insuficientes
404 NOT_FOUND Recurso não existe
409 CONFLICT Conflito de recurso (ex: email já registrado)
429 RATE_LIMITED Taxa de requisições excedida
500 INTERNAL_ERROR Erro interno do servidor

(3) Formato de Resposta

TYPESCRIPT
// Resposta de sucesso
{
  "data": { ... },
  "message": "Operation successful"
}

// Resposta de lista
{
  "items": [...],
  "total": 1000000,
  "page": 1,
  "limit": 20
}

// Resposta de erro
{
  "statusCode": 400,
  "message": "Validation error",
  "errorCode": "VALIDATION_ERROR",
  "details": { "field": "email", "reason": "Invalid format" }
}

7. Exemplo Completo: Estrutura do Projeto MegaShop

TEXT
megashop/
├── nuxt.config.ts
├── prisma/
│   ├── schema.prisma
│   ├── seed.ts
│   └── migrations/
├── pages/
│   ├── index.vue
│   ├── products/
│   │   ├── index.vue
│   │   └── [id].vue
│   ├── categories/
│   │   └── [slug].vue
│   ├── cart.vue
│   ├── checkout.vue
│   ├── login.vue
│   ├── register.vue
│   ├── profile/
│   │   ├── index.vue
│   │   └── orders.vue
│   └── admin/
│       ├── index.vue
│       ├── products/
│       └── orders/
├── components/
│   ├── AppHeader.vue
│   ├── AppFooter.vue
│   ├── product/
│   │   ├── ProductCard.vue
│   │   ├── ProductGrid.vue
│   │   └── ProductReview.vue
│   ├── cart/
│   │   └── CartItem.vue
│   └── common/
│       ├── LanguageSwitcher.vue
│       └── SearchBar.vue
├── composables/
│   ├── useCart.ts
│   ├── useAnalytics.ts
│   ├── useLocalizedPrice.ts
│   └── useProductSearch.ts
├── stores/
│   ├── cart.ts
│   └── user.ts
├── server/
│   ├── utils/
│   │   ├── prisma.ts
│   │   └── jwt.ts
│   ├── middleware/
│   │   └── auth.ts
│   ├── api/
│   │   ├── auth/
│   │   ├── products/
│   │   ├── categories/
│   │   ├── cart/
│   │   └── orders/
│   └── plugins/
│       └── stock.ts
├── middleware/
│   ├── 01-auth.global.ts
│   └── admin.ts
├── plugins/
│   ├── 01-config.ts
│   ├── 02-logger.ts
│   └── 03-stripe.client.ts
├── layouts/
│   ├── default.vue
│   └── sidebar.vue
├── locales/
│   ├── en.json
│   ├── zh.json
│   └── ja.json
├── modules/
│   └── analytics/
├── tests/
│   ├── composables/
│   ├── stores/
│   ├── components/
│   └── api/
├── e2e/
│   ├── cart-flow.spec.ts
│   ├── auth-flow.spec.ts
│   └── admin-flow.spec.ts
├── Dockerfile
├── docker-compose.yml
├── .github/workflows/
│   ├── ci.yml
│   ├── deploy-staging.yml
│   └── deploy-production.yml
└── public/
    ├── favicon.ico
    └── robots.txt

❓ Perguntas Frequentes

P Quanto tempo leva a fase de design?
R Geralmente 1-2 semanas. Análise de requisitos: 2 dias; design de arquitetura: 2 dias; modelagem de dados: 2 dias; especificações de API: 2 dias; seleção tecnológica: 1 dia. Quanto mais detalhado o design, mais suave o processo de desenvolvimento.
P Como escolher entre PostgreSQL e MySQL?
R PostgreSQL é mais adequado para o MegaShop—suporta campos JSON (atributos de produto), busca full-text (busca de produtos) e uma ampla variedade de tipos de índice. O Prisma oferece o melhor suporte para PostgreSQL.
P Redis é obrigatório?
R Recomendado para páginas de produto com milhões de itens. Redis é usado para cache de produto e armazenamento ISR, com tempo de resposta de 5 ms comparado a 200 ms do banco de dados. Para cenários de baixo tráfego, pode ser ignorado por enquanto.
P Como é tratado o versionamento de API?
R Adicione o prefixo de versão /api/v1/products à URL, e incremente o número da versão para mudanças principais. Para mudanças menores, estenda os campos de forma retrocompatível.
P Como deve ser determinada a granularidade da divisão de módulos?
R Divida por domínio de negócio—um módulo para autenticação, produtos, carrinho de compras e pedidos. Cada módulo deve ter sua própria API, Store, Composable e página. Não divida por camada técnica.
P Como garantir a consistência entre a documentação de design e o código?
R Use o schema Prisma como a fonte única de verdade para o modelo de dados, e defina as especificações de API usando interfaces TypeScript. Ao fazer alterações de design, atualize primeiro o schema e as interfaces, depois atualize o código.

📖 Resumo


📝 Exercícios

  1. Questão Básica (Dificuldade: ⭐): Desenhe um diagrama mostrando as funções de usuário e módulos funcionais do seu projeto.
  2. Problema Avançado (Dificuldade ⭐⭐): Projete um schema Prisma completo (com pelo menos 5 modelos), considerando índices e chaves estrangeiras.
  3. Desafio (Dificuldade: ⭐⭐⭐): Projete um documento completo de especificação de API, incluindo todos os endpoints, formatos de requisição/resposta e códigos de erro.

---|

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%