\n\n```\n\n**Сжатие изображений:**\n```bash\n# WebP для современных браузеров\nffmpeg -i image.jpg -vcodec libwebp -quality 80 image.webp\n\n# JPEG optimization\njpegtran -copy none -optimize -progressive image.jpg -o image-optimized.jpg\n```\n\n### 9. Headers для оптимальной доставки\n\n**Nginx конфиг:**\n```nginx\nlocation /static/ {\n alias /var/www/static/;\n \n # Кеширование\n expires 30d;\n add_header Cache-Control \"public, immutable\";\n \n # Сжатие\n gzip on;\n gzip_types text/css application/javascript image/svg+xml font/woff2;\n \n # Безопасность\n add_header X-Content-Type-Options \"nosniff\";\n add_header X-Frame-Options \"DENY\";\n add_header X-XSS-Protection \"1; mode=block\";\n}\n```\n\n### 10. Мониторинг и метрики\n\n**CloudWatch метрики (AWS):**\n```python\nimport boto3\n\ncloudwatch = boto3.client('cloudwatch')\n\ndef log_request_count(bucket: str):\n cloudwatch.put_metric_data(\n Namespace='S3',\n MetricData=[\n {\n 'MetricName': 'RequestCount',\n 'Value': 1,\n 'Dimensions': [{'Name': 'BucketName', 'Value': bucket}]\n }\n ]\n )\n```\n\n### Чеклист deployment статики\n\n- Используешь Nginx для раздачи\n- Включен gzip compression\n- Установлены правильные Cache-Control headers\n- Версионирование файлов (cache busting)\n- Изображения оптимизированы\n- Используется CDN (CloudFront, Cloudflare)\n- Настроены SSL/TLS сертификаты\n- Мониторинг доставки\n- CORS заголовки если нужно\n\n### Сравнение подходов\n\n| Метод | Скорость | Масштабируемость | Стоимость |\n|-------|----------|------------------|----------|\n| Django/FastAPI | Медленно | Плохо | Низка |\n| Nginx + диск | Быстро | Среднее | Низка |\n| S3 + CDN | Очень быстро | Отличное | Средняя |\n| Cloudflare | Очень быстро | Отличное | Низка |\n\n### Вывод\n\nДля production:\n1. **Никогда** не отдавай статику через приложение\n2. Используй **Nginx** как reverse proxy\n3. Кешируй на **30+ дней** с cache busting\n4. Храни в **S3** для масштабируемости\n5. Раздавай через **CDN** для скорости\n6. Сжимай **gzip** на лету","dateCreated":"2026-03-22T20:32:54.049881","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как отдаешь статические файлы на production?

2.0 Middle🔥 131 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Раздача статических файлов на Production

Доставка статических файлов (CSS, JS, изображения, шрифты) — критична для производительности. На production это делается правильно, а не через приложение.

1. НЕ используй FastAPI/Django для статики

Плохо:

# FastAPI НЕ должен отдавать статику
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")

Почему это плохо:

  • Блокирует worker процессы
  • Медленно (нет кеширования)
  • Нет сжатия gzip
  • Нет CDN

2. Правильный подход: Nginx + S3/CDN

Архитектура:

Клиент
  ├─ /api/* → Nginx → FastAPI (Gunicorn)
  └─ /static/* → Nginx → disk или S3/CloudFront

3. Nginx конфигурация

nginx.conf:

server {
    listen 80;
    server_name example.com;

    # Кеширование статики
    location /static/ {
        alias /var/www/static/;
        expires 30d;  # Браузер кешет на 30 дней
        add_header Cache-Control "public, immutable";
        add_header X-Content-Type-Options "nosniff";
        gzip on;  # Сжимаем на лету
        gzip_types text/css application/javascript image/svg+xml;
    }

    # API
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Остальное
    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}

4. Django + Whitenoise (если нужна статика)

Если всё же необходимо отдавать статику из приложения:

pip install whitenoise

settings.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',  # После SecurityMiddleware
    # ...
]

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

# Включаем сжатие и кеширование
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Запуск:

python manage.py collectstatic --no-input
gunicorn config.wsgi

5. FastAPI + Amazon S3 (Best Practice)

Загрузка файлов в S3 (бэкенд):

from fastapi import FastAPI, UploadFile, File
import boto3
from datetime import datetime

app = FastAPI()

s3_client = boto3.client(
    's3',
    aws_access_key_id=os.getenv('AWS_ACCESS_KEY'),
    aws_secret_access_key=os.getenv('AWS_SECRET_KEY'),
    region_name='us-east-1'
)

S3_BUCKET = os.getenv('S3_BUCKET_NAME')

@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
    # Генерируем уникальное имя
    timestamp = datetime.now().timestamp()
    key = f"uploads/{timestamp}_{file.filename}"
    
    # Загружаем в S3
    s3_client.upload_fileobj(
        file.file,
        S3_BUCKET,
        key,
        ExtraArgs={
            'ContentType': file.content_type,
            'CacheControl': 'max-age=86400'  # 1 день
        }
    )
    
    # Возвращаем публичный URL
    url = f"https://{S3_BUCKET}.s3.amazonaws.com/{key}"
    return {"url": url, "filename": file.filename}

6. CloudFront CDN (распределённая доставка)

Terraform конфиг:

resource "aws_cloudfront_distribution" "static" {
  origin {
    domain_name = "${aws_s3_bucket.static.id}.s3.amazonaws.com"
    origin_id   = "S3Origin"
  }

  enabled = true
  
  default_cache_behavior {
    allowed_methods = ["GET", "HEAD"]
    cached_methods  = ["GET", "HEAD"]
    target_origin_id = "S3Origin"
    
    # Кеширование на 30 дней
    min_ttl     = 0
    default_ttl = 86400
    max_ttl     = 2592000
    
    viewer_protocol_policy = "redirect-to-https"
  }
  
  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
  
  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

7. Docker-compose для production

docker-compose.yml:

version: "3.9"
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./static:/var/www/static:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - app

  app:
    build: .
    environment:
      - DATABASE_URL=postgresql://...
    expose:
      - 8000
    volumes:
      - ./app:/app
    command: gunicorn -w 4 -b 127.0.0.1:8000 app:app

  postgres:
    image: postgres:15
    environment:
      - POSTGRES_DB=app
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

8. Оптимизация статики

Версионирование файлов (cache busting):

# frontend/build/manifest.json
{
  "main.js": "main.d4f5c3a2.js",
  "main.css": "main.7e8b9f1c.css"
}

В шаблоне:

<script src="/static/{{ manifest['main.js'] }}"></script>
<link rel="stylesheet" href="/static/{{ manifest['main.css'] }}">

Сжатие изображений:

# WebP для современных браузеров
ffmpeg -i image.jpg -vcodec libwebp -quality 80 image.webp

# JPEG optimization
jpegtran -copy none -optimize -progressive image.jpg -o image-optimized.jpg

9. Headers для оптимальной доставки

Nginx конфиг:

location /static/ {
    alias /var/www/static/;
    
    # Кеширование
    expires 30d;
    add_header Cache-Control "public, immutable";
    
    # Сжатие
    gzip on;
    gzip_types text/css application/javascript image/svg+xml font/woff2;
    
    # Безопасность
    add_header X-Content-Type-Options "nosniff";
    add_header X-Frame-Options "DENY";
    add_header X-XSS-Protection "1; mode=block";
}

10. Мониторинг и метрики

CloudWatch метрики (AWS):

import boto3

cloudwatch = boto3.client('cloudwatch')

def log_request_count(bucket: str):
    cloudwatch.put_metric_data(
        Namespace='S3',
        MetricData=[
            {
                'MetricName': 'RequestCount',
                'Value': 1,
                'Dimensions': [{'Name': 'BucketName', 'Value': bucket}]
            }
        ]
    )

Чеклист deployment статики

  • Используешь Nginx для раздачи
  • Включен gzip compression
  • Установлены правильные Cache-Control headers
  • Версионирование файлов (cache busting)
  • Изображения оптимизированы
  • Используется CDN (CloudFront, Cloudflare)
  • Настроены SSL/TLS сертификаты
  • Мониторинг доставки
  • CORS заголовки если нужно

Сравнение подходов

МетодСкоростьМасштабируемостьСтоимость
Django/FastAPIМедленноПлохоНизка
Nginx + дискБыстроСреднееНизка
S3 + CDNОчень быстроОтличноеСредняя
CloudflareОчень быстроОтличноеНизка

Вывод

Для production:

  1. Никогда не отдавай статику через приложение
  2. Используй Nginx как reverse proxy
  3. Кешируй на 30+ дней с cache busting
  4. Храни в S3 для масштабируемости
  5. Раздавай через CDN для скорости
  6. Сжимай gzip на лету
Как отдаешь статические файлы на production? | PrepBro