Laravel довольно популярный на сегодня фреймворк. На этом фреймворке можно быстро и легко создавать веб-сайты. В отличии от cms, как WordPress, Drupal, Zoomla и т.д., мы не можем установить готовые плагины для улучшения нашего приложения laravel всего за несколько кликов, но Laravel умеет из коробки много функций оптимизации скорости для ускорения вашего сайта. Если вы ищете пошаговое руководство для повышения скорости веб-сайта, то этот пост для вас. В этом посте я покажу вам как увеличить скорость и производительность страниц вашего сайта laravel.
План работы
- Минификация HTML
- Кэширование маршрутов
- Кэширование запросов
- Кэширование конфигурации
- Bundle & Minify CSS/Js
- Оптимизация изображений
- Ленивая загрузка
- Оптимизация htaccess
- Более быстрый сервер веб-хостинг
- CDN
Перед началом работы по ускорению, советую посмотреть текущие результаты в Google Page speed, GT Metrix или Pingdom, а затем сравнить улучшения до и после.
1. Минификация HTML
Во время разметки HTML мы сохраняем много пробелов для отступов и повышения читабельности кода. Браузер не заботится о пробелах и отступах, но именно пробелы делают наш HTML-файл больше и влияют на скорость страницы. Мы можем легко уменьшить размер HTML-страницы, объединив HTML с помощью middleware Laravel. Давайте сделаем модификацию HTML с помощью него в laravel.
php artisan make:middleware HtmlMifier
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Response;
class HtmlMifier
{
public function handle($request, Closure $next)
{
$response = $next($request);
$contentType = $response->headers->get('Content-Type');
if (strpos($contentType, 'text/html') !== false) {
$response->setContent($this->minify($response->getContent()));
}
return $response;
}
public function minify($input)
{
$search = [
'/\>\s+/s',
'/\s+</s',
];
$replace = [
'> ',
' <',
];
return preg_replace($search, $replace, $input);
}
}
Добавьте ваш middleware в kernel.php в $routeMiddlewareGroup
массив
protected $routeMiddleware = [
...,
...,
'HtmlMinifier' => '\App\Http\Middleware\HtmlMinifier',
]
Теперь мы можем использовать этот middleware в нашем файле маршрута. Для каждого запроса на нашем сайте этот middleware будет автоматически выполнять модификацию HTML и отдавать пользователю сжатый контент.
Route::group(['middleware'=>'HtmlMinifier'], function(){
Route::get('/', 'SiteController@home');
Route::get('/{slug}', 'SiteController@postDetails');
...
...
});
2. Кэширование маршрутов
Мы можем получить большую скорость запроса-ответа, используя кэширование маршрутов Laravel. Чтобы сделать кэширование маршрута, выполните команду, приведенную ниже.
php artisan route:cache
Эта команда кэширует все маршруты в файле routes.php в каталог bootstrap/cache. Если позже вам нужно будет добавить еще один маршрут или отредактировать его, вам придется очистить кэш маршрутов и сгенерировать его заново.
php artisan route:clear
3. Кэширование запросов
Предположим, у нас есть 50 записей в блоге и каждый день 1 тысяча посетителей посещают наш сайт. В этой ситуации всякий раз, когда посетитель читает сообщение, он обращается к базе данных для получения сообщения и это занимает время. Ваш сайт становится от этого немного медленнее. Мы можем легко решить эту проблему, кэшируя наш пост. Когда любой пользователь читает сообщение в блоге, оно хранится в нашем кэше, а затем для других посетителей сообщение будет подаваться из нашего кэша, а не браться из нашей базы данных. Так что больше никаких запросов к базе данных и получите более быстрый ответ. Это круто! Давайте сделаем это.
// example.com/awesome-post-title
public function postDetails($slug){
$post = Cache::rememberForever('posts.'.$slug, function($slug) use($slug) {
return Post::where('slug',$slug)->first();
});
return view('frontend.posts.post-details',['post'=>$post]);
}
Смотрите, здесь я передаю post slug, который уникален для каждого поста для SEO-friendly URL-адреса.
Если мы обновим наш пост, то в данном случае пользователи все равно будут продолжать получать данные из кеша. Немного доработаем нашу модель поста.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public static function boot()
{
parent::boot();
static::updating(function ($instance) {
// update cache content
Cache::put('posts.'.$instance->slug,$instance);
});
static::deleting(function ($instance) {
// delete post cache
Cache::forget('posts.'.$instance->slug);
});
}
}
4. Кэширование конфигурации
php artisan config:cache
Эта команда кэширует всю конфигурацию в файл config.php в каталог bootstrap/cache. Если вам нужно добавить / изменить настройки, то вам придется очистить config-cache и повторно сгенерировать его снова. Чтобы очистить кэш конфигурации, выполните команду, приведенную ниже.
php artisan config:clear
5. Bundle & Minify CSS/Js
На каждом сайте имеется css/js статик файлы. На 1 странице их может быть десятки. Подумайте о том, что если наш сайт имеет 20-25 различных ссылок на файлы CSS/Js, то он будет делать больше HTTP-запросов на наш сервер для загрузки ресурсов, и это еще один фактор замедления сайта. Мы можем сделать пакет для CSS и минимизировать CSS-файлы и js-файл для удаления лишних пробелов и отступов с помощью Webpack, Gulp, Grunt или любых других инструментов bundler. Это поможет нам склеить все CSS-файлы в один файл,а все Js-файлы – в один файл JS. Это поможет нам уменьшить кол-во HTTP-запросов и сайт загрузится быстрее, чем раньше. Вот пример Laravel mix.
//css bundle
mix.styles([
'public/css/vendor/bootstrap.min.css',
'public/css/style.css'
], 'public/bundle/app.css');
//js bundle
mix.scripts([
'public/js/vendor/jquery-2.1.4.js',
'public/js/vendor/bootstrap.min.js',
'public/js/functions.js'
], 'public/bundle/app.js');
npm run production
6. Оптимизация изображений
Изображения довольно важная часть внешнего вида любого сайта. Каждая картинка весит намного больше, чем текстовый контент. Изображения оказывают большое влияние на отчеты Google Page speed insights. Мы можем использовать TinyPng, Cloudinary, Squoosh для получения более оптимизированных изображений. Оптимизированные изображения могут сэкономить пропускную способность, а также быстро загрузить наш сайт.
Пример оптимизированного изображения
Мы можем настроить lazy-load изображений на странице сайта. Это очень удобно, потому что с помощью этого метода загружаются только те изображения, которые в данный момент видны на экране. Когда пользователь прокручивает страницу, то он будет загружать остальные изображения, так что веб-страница загружается быстрее. Чтобы реализовать ленивую загрузку изображения, просто добавьте lazy="loading"
атрибут в свой img
тег.
7. Нетерпеливая загрузка
Нетерпеливая загрузка очень эффективна для загрузки данных из базы данных с меньшим количеством операций с базой данных. Это решает проблему запроса N+1. Получить данные из бд с как можно меньшим кол-вом запросов и их оптимизация – это очень полезно для повышения производительности сайт. Давайте рассмотрим пример.
Предположим, у нас есть модель Post, и она имеет отношение “один-много” с моделью комментариев.
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
Без Нетерпеливой Загрузки
Теперь, если мы запустим цикл коллекции Post, под капотом он выполнит запрос N+1 Без нетерпеливой загрузки это убьет производительность на больших данных.
$posts = Post::all();
foreach ($posts as $post) {
echo $post->name;
$comments = $post->comments;
foreach($comments as $comment){
// do something
}
}
Этот код генерирует N+1 взаимодействие с базой данных. Если наша таблица post содержит 100 сообщений, то она будет генерировать 100 + 1 запрос. 1 для получения сообщений из таблицы сообщений и еще 100 запросов для каждого комментария к сообщению.
# query for N number of post
SELECT * FROM posts;
# For each N post it will run also
SELECT * FROM comments WHERE post_id = 1
SELECT * FROM comments WHERE post_id = 2
SELECT * FROM comments WHERE post_id = 3
.....
С Нетерпеливой Загрузкой
Теперь, если мы используем функцию нетерпеливой загрузки, то она выполнит оптимизированный запрос для нас.
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
echo $post->name;
$comments = $post->comments;
foreach($comments as $comment){
// do something
}
}
Теперь с нетерпеливой загрузкой он будет выполнять только два запроса, как показано ниже.
# First query
SELECT * FROM posts;
# Second query
SELECT * FROM comments WHERE post_id IN (1, 2, 3, 4, 5, ...);
8. Оптимизация htaccess
Оптимизация Laravel htaccess может быть использована для увеличения скорости страницы вашего сайта с помощью кэширования изображений, сжатия HTML, сжатия Gzip, включения кэширования браузера, истечения срока действия заголовков для использования кэширования браузера.
Откройте файл htaccess и добавьте фрагмент кода, приведенный ниже, в конце вашего сайта.
Файл htaccess очень важен для сервера, и он очень мощен для воздействия на ваш веб-сервер Linux. Перед любыми изменениями, пожалуйста, сначала сохраните резервную копию.
## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType application/javascript "access 1 month"
ExpiresByType application/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 2 days"
</IfModule>
# GZIP COMPRESSION
# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
# compress HTML
<files *.html>
SetOutputFilter DEFLATE
</files>
# GZIP COMPRESSION
9. Используйте CDN
Если ваш сайт имеет высокий трафик из другого региона, то используйте CDN (сеть доставки контента). Он будет доставлять контент вашего сайта с низкой задержкой в сети. Немного резюмируя, предположим, что у вас есть сайт и его хостинг-сервер расположен в США, а вы посетители из США, и большинство посетителей из Европы и Азии. Для пользователей, которые находятся далеко от вашего сервера, время загрузки веб-сайта становится выше, потому что информация перемещается на большое расстояние для вашего посетителя. В этой ситуации вы можете использовать CDN-сервер для посетителей из Европы или Азии. Если вы хотите использовать CDN для своего веб-сайта, то они могут быть лучшим вариантом для вас, приведенным ниже
- MaxCDN
- Cloud Flash