Оптимізація TTFB (Time to First Byte)
TTFB — час від відправки запиту до отримання першого байта від сервера. Добре значення: ≤ 800 мс (Google вважає прийнятним до 600 мс). TTFB напрямски впливає на LCP: неможливо мати хороший LCP при поганому TTFB.
З чого складається TTFB
DNS → TCP → TLS → Запит → Обробка на сервері → Перший байт відповіді
Типовий розподіл:
- DNS lookup: 10–100 мс (вирішується через preconnect + CDN)
- TCP + TLS: 30–150 мс (вирішується через HTTP/2, CDN)
- Server processing: 50–3000+ мс (найбільш керована частина)
Full Page Cache
Найефективніший спосіб: кешувати готовий HTML.
// spatie/laravel-responsecache або кастомне рішення
// Middleware додається для гостьових запитів GET
class FullPageCache
{
private const TTL = 300; // 5 хвилин
public function handle(Request $request, Closure $next): Response
{
if (!$this->isCacheable($request)) {
return $next($request);
}
$key = $this->cacheKey($request);
if (Cache::has($key)) {
return response(Cache::get($key))
->header('X-Cache', 'HIT')
->header('Content-Type', 'text/html; charset=UTF-8');
}
$response = $next($request);
if ($response->getStatusCode() === 200) {
Cache::put($key, $response->getContent(), self::TTL);
}
return $response->header('X-Cache', 'MISS');
}
private function isCacheable(Request $request): bool
{
return $request->isMethod('GET')
&& !auth()->check()
&& !$request->hasCookie(session()->getName());
}
private function cacheKey(Request $request): string
{
return 'fpc:' . sha1($request->fullUrl());
}
}
Nginx FastCGI Cache
Кеш на рівні nginx — швидше ніж кеш у PHP/Redis:
# nginx.conf
fastcgi_cache_path /var/cache/nginx/fcgi
levels=1:2
keys_zone=LARAVEL:10m
inactive=60m
max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
location ~ \.php$ {
fastcgi_cache LARAVEL;
fastcgi_cache_valid 200 5m;
fastcgi_cache_valid 404 1m;
# Не кешувати для авторизованих
fastcgi_cache_bypass $cookie_laravel_session $http_authorization;
fastcgi_no_cache $cookie_laravel_session $http_authorization;
add_header X-Fastcgi-Cache $upstream_cache_status;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
Інвалідація по тегу (через nginx-cache-purge модуль):
curl -X PURGE https://example.ru/products/iphone-15-pro
Оптимізація запитів до бази даних
// Повільний запит: N+1 проблема
$products = Product::all();
foreach ($products as $product) {
echo $product->category->name; // N+1 запитів до categories
}
// Швидко: eager loading
$products = Product::with(['category', 'images', 'brand'])->get();
// Профілювання повільних запитів
DB::listen(function ($query) {
if ($query->time > 100) {
Log::warning('Slow query', [
'sql' => $query->sql,
'time' => $query->time,
]);
}
});
Redis для кешування даних
// Кеш результатів важких запитів
$categories = Cache::remember('categories:tree', 3600, function () {
return Category::with('children')
->whereNull('parent_id')
->orderBy('sort_order')
->get();
});
// Кеш лічильників
$stats = Cache::remember('product:stats:' . $productId, 300, function () use ($productId) {
return [
'views' => ProductView::where('product_id', $productId)->count(),
'sales' => OrderItem::where('product_id', $productId)->sum('quantity'),
'wishlist' => WishlistItem::where('product_id', $productId)->count(),
];
});
DNS та мережеві оптимізації
<!-- Preconnect до критичних ресурсів -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.ru" crossorigin>
<link rel="dns-prefetch" href="https://analytics.google.com">
OPcache для PHP
; php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; 0 у production
opcache.jit=tracing
opcache.jit_buffer_size=64M
Цільові значення за типами запитів
| Тип сторінки | З кешем | Без кешу |
|---|---|---|
| Головна | < 50 мс | < 300 мс |
| Каталог | < 50 мс | < 400 мс |
| Карточка товару | < 50 мс | < 200 мс |
| API-точки входу | — | < 100 мс |
Час оптимізації: 2–3 дні для налаштування кешування та профілювання запитів.







