Зачем ставить десяток плагинов, если можно обойтись парой строк кода?

Каждый новый плагин — это лишняя нагрузка, потенциальная уязвимость и конфликт в будущем. Вот 15 реальных задач, которые обычно решают плагинами, но можно обойтись чистым кодом.

Краткое содержание

🚀 1. Ускорение сайта вместо плагинов кеширования

Вместо: WP Rocket, W3 Total Cache, WP Super Cache
Достаточно:

php
// В functions.php // Браузерное кеширование add_action('init', function() { if (!is_admin()) { header('Cache-Control: public, max-age=31536000'); header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT'); } }); // Сжатие HTML на лету add_action('template_redirect', function() { ob_start(function($buffer) { $search = ['/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s']; $replace = ['>', '<', '\\1']; return preg_replace($search, $replace, $buffer); }); });

Результат: Ускорение на 20-40% без плагинов.

🛡️ 2. Защита вместо плагинов безопасности

Вместо: Wordfence, iThemes Security, Sucuri
Достаточно:

php
// В wp-config.php // Блокировка XML-RPC (используется для брутфорса) add_filter('xmlrpc_enabled', '__return_false'); // Запрет на редактирование файлов из админки define('DISALLOW_FILE_EDIT', true); // В functions.php // Защита от входа с логином 'admin' add_filter('authenticate', function($user, $username, $password) { if ($username === 'admin') { return new WP_Error('denied', 'Недопустимый логин'); } return $user; }, 10, 3); // Ограничение попыток входа add_action('wp_login_failed', function($username) { $failed_logins = get_transient('failed_login_' . $_SERVER['REMOTE_ADDR']) ?: 0; $failed_logins++; set_transient('failed_login_' . $_SERVER['REMOTE_ADDR'], $failed_logins, 300); if ($failed_logins > 5) { // Блокировка на 15 минут set_transient('blocked_ip_' . $_SERVER['REMOTE_ADDR'], true, 900); } }); // Проверка блокировки перед входом add_action('login_init', function() { if (get_transient('blocked_ip_' . $_SERVER['REMOTE_ADDR'])) { wp_die('Слишком много попыток входа. Попробуйте через 15 минут.', 403); } });

📱 3. Ленивая загрузка изображений

Вместо: Lazy Load, WP Rocket, Smush
Достаточно:

php
// Добавляем loading="lazy" ко всем изображениям add_filter('the_content', function($content) { return preg_replace_callback('/<img([^>]+)>/', function($matches) { $img = $matches[1]; if (!preg_match('/loading=[\'"]/', $img)) { $img = ' loading="lazy" ' . $img; } return '<img' . $img . '>'; }, $content); }); // WebP для поддерживающих браузеров add_filter('wp_get_attachment_image_src', function($image, $id, $size, $icon) { if ($image && strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) { $webp_path = str_replace(['.jpg', '.jpeg', '.png'], '.webp', $image[0]); if (file_exists(ABSPATH . parse_url($webp_path, PHP_URL_PATH))) { $image[0] = $webp_path; } } return $image; }, 10, 4);

📧 4. Форма обратной связи

Вместо: Contact Form 7, WPForms, Gravity Forms
Достаточно:

php
// В functions.php
// Создаем шорткод для простой формы
add_shortcode('simple_contact_form', function() {
    ob_start();
    ?>
    <form method="post" class="contact-form"> <input type="text" name="name" placeholder="Ваше имя" required> <input type="email" name="email" placeholder="Email" required> <textarea name="message" placeholder="Сообщение" required></textarea> <button type="submit">Отправить</button> </form> <?php
    return ob_get_clean();
});

// Обработчик формы
add_action('init', function() {
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['name'])) {
        $to = get_option('admin_email');
        $subject = 'Новое сообщение с сайта ' . get_bloginfo('name');
        $message = "Имя: {$_POST['name']}\nEmail: {$_POST['email']}\n\n{$_POST['message']}";
        $headers = "From: {$_POST['email']}";
        
        if (wp_mail($to, $subject, $message, $headers)) {
            wp_redirect(add_query_arg('sent', '1'));
            exit;
        }
    }
});

🔍 5. SEO-оптимизация

Вместо: Yoast SEO, Rank Math, All in One SEO
Достаточно:

php
// Автоматические мета-теги
add_action('wp_head', function() {
    if (is_single() || is_page()) {
        global $post;
        $description = wp_trim_words(strip_tags($post->post_content), 20);
        ?>
        <meta name="description" content="<?php echo esc_attr($description); ?>"> <meta property="og:title" content="<?php the_title(); ?>"> <meta property="og:description" content="<?php echo esc_attr($description); ?>"> <meta property="og:image" content="<?php echo get_the_post_thumbnail_url($post->ID, 'large'); ?>"> <?php
    }
});

// Автоматический alt для изображений
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment) {
    if (empty($attr['alt'])) {
        $attr['alt'] = get_the_title($attachment->post_parent) ?: get_bloginfo('name');
    }
    return $attr;
}, 10, 2);

🗺️ 6. Карта сайта sitemap.xml

Вместо: Google XML Sitemaps, Yoast SEO sitemap
Достаточно:

php
// Создаем sitemap.xml на лету
add_action('init', function() {
    if ($_SERVER['REQUEST_URI'] === '/sitemap.xml') {
        header('Content-Type: application/xml');
        
        $posts = get_posts(['posts_per_page' => -1, 'post_type' => ['post', 'page']]);
        
        echo '<?xml version="1.0" encoding="UTF-8"?>';
        echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
        
        foreach ($posts as $post) {
            echo '<url>';
            echo '<loc>' . get_permalink($post->ID) . '</loc>';
            echo '<lastmod>' . get_the_modified_date('c', $post) . '</lastmod>';
            echo '<changefreq>monthly</changefreq>';
            echo '<priority>' . ($post->post_type === 'page' ? '0.8' : '0.6') . '</priority>';
            echo '</url>';
        }
        
        echo '</urlset>';
        exit;
    }
});

🔗 7. Редиректы и 301 перенаправления

Вместо: Redirection, Simple 301 Redirects
Достаточно:

php
// В functions.php add_action('template_redirect', function() { $redirects = [ '/old-page/' => '/new-page/', '/blog/2020/' => '/blog/', // Добавьте свои редиректы ]; $current_url = $_SERVER['REQUEST_URI']; if (isset($redirects[$current_url])) { wp_redirect(home_url($redirects[$current_url]), 301); exit; } }); // Автоматический редирект со старого домена if ($_SERVER['HTTP_HOST'] === 'stary-domen.ru') { wp_redirect('https://noviy-domen.ru' . $_SERVER['REQUEST_URI'], 301); exit; }

📊 8. Счетчик просмотров

Вместо: Post Views Counter, WP-PostViews
Достаточно:

php
// Счетчик просмотров function increment_post_views($post_id = null) { if (!$post_id) { global $post; $post_id = $post->ID; } $count = get_post_meta($post_id, 'views', true) ?: 0; $count++; update_post_meta($post_id, 'views', $count); return $count; } // Автоматически считаем при просмотре add_action('wp_head', function() { if (is_single()) { increment_post_views(); } }); // Шорткод для вывода просмотров add_shortcode('post_views', function($atts) { $atts = shortcode_atts(['id' => null], $atts); $post_id = $atts['id'] ?: get_the_ID(); $views = get_post_meta($post_id, 'views', true) ?: 0; return number_format($views, 0, ',', ' ') . ' просмотров'; });

🖼️ 9. Оптимизация изображений

Вместо: Smush, Imagify, ShortPixel
Достаточно:

php
// Автоматическое сжатие при загрузке add_filter('wp_handle_upload', function($file) { if ($file['type'] === 'image/jpeg' || $file['type'] === 'image/png') { $image = $file['type'] === 'image/jpeg' ? imagecreatefromjpeg($file['file']) : imagecreatefrompng($file['file']); // Сжатие до 85% качества imagejpeg($image, $file['file'], 85); imagedestroy($image); } return $file; }); // Автоматическое создание WebP копий add_filter('wp_generate_attachment_metadata', function($metadata, $attachment_id) { $file = get_attached_file($attachment_id); $webp_file = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $file); if (!file_exists($webp_file)) { $image = wp_get_image_editor($file); if (!is_wp_error($image)) { $image->save($webp_file, 'image/webp'); } } return $metadata; }, 10, 2);

🔔 10. Уведомления о новых комментариях

Вместо: Subscribe to Comments, WP Comment Notifier
Достаточно:

php
// Уведомление автора поста о новом комментарии add_action('comment_post', function($comment_id, $comment_approved) { if ($comment_approved === 1) { $comment = get_comment($comment_id); $post = get_post($comment->comment_post_ID); $author = get_userdata($post->post_author); if ($author && $author->user_email !== $comment->comment_author_email) { $subject = 'Новый комментарий к вашей записи: ' . $post->post_title; $message = "Кто-то прокомментировал вашу запись:\n\n"; $message .= "Автор: {$comment->comment_author}\n"; $message .= "Текст: {$comment->comment_content}\n\n"; $message .= "Ссылка: " . get_permalink($post->ID) . "#comment-{$comment_id}"; wp_mail($author->user_email, $subject, $message); } } }, 10, 2);

📋 11. Хлебные крошки

Вместо: Breadcrumb NavXT, Yoast SEO breadcrumbs
Достаточно:

php
// Шорткод для хлебных крошек add_shortcode('breadcrumbs', function() { global $post; $crumbs = ['<a href="' . home_url() . '">Главная</a>']; if (is_single()) { $categories = get_the_category($post->ID); if ($categories) { $category = $categories[0]; $crumbs[] = '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a>'; } $crumbs[] = get_the_title(); } elseif (is_page()) { if ($post->post_parent) { $parent_id = $post->post_parent; $parents = []; while ($parent_id) { $parent = get_post($parent_id); $parents[] = '<a href="' . get_permalink($parent->ID) . '">' . $parent->post_title . '</a>'; $parent_id = $parent->post_parent; } $crumbs = array_merge($crumbs, array_reverse($parents)); } $crumbs[] = get_the_title(); } elseif (is_category()) { $cat = get_queried_object(); $crumbs[] = $cat->name; } return '<div class="breadcrumbs">' . implode(' &raquo; ', $crumbs) . '</div>'; });

📝 12. Похожие записи

Вместо: Yet Another Related Posts Plugin, Related Posts
Достаточно:

php
// Шорткод для похожих записей add_shortcode('related_posts', function($atts) { $atts = shortcode_atts([ 'count' => 3, 'category' => null ], $atts); global $post; $categories = wp_get_post_categories($post->ID, ['fields' => 'ids']); $args = [ 'post_type' => 'post', 'posts_per_page' => $atts['count'], 'post__not_in' => [$post->ID], 'category__in' => $categories, 'orderby' => 'rand' ]; $query = new WP_Query($args); if (!$query->have_posts()) { return ''; } $output = '<div class="related-posts"><h3>Похожие статьи</h3><ul>'; while ($query->have_posts()) { $query->the_post(); $output .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>'; } wp_reset_postdata(); $output .= '</ul></div>'; return $output; });

🔐 13. Защита от горячих ссылок (hotlink protection)

Вместо: плагины для защиты изображений
Достаточно в .htaccess:

apache
# Блокировка горячих ссылок
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?вашсайт\.ru [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [NC,F,L]

# Или показывать другую картинку
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?вашсайт\.ru [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ /images/hotlink.jpg [NC,R,L]

Или через PHP:

php
// Проверка реферера для медиафайлов add_action('template_redirect', function() { if (is_attachment()) { $referer = $_SERVER['HTTP_REFERER'] ?? ''; $allowed_domains = [ 'вашсайт.ru', 'www.вашсайт.ru', 'google.com', 'yandex.ru' ]; $allowed = false; foreach ($allowed_domains as $domain) { if (strpos($referer, $domain) !== false) { $allowed = true; break; } } if (!$allowed && !empty($referer)) { wp_redirect(home_url('/hotlink-blocked/'), 302); exit; } } });

📰 14. RSS-фид с улучшениями

Вместо: плагины для улучшения RSS
Достаточно:

php
// Добавляем изображения в RSS
add_filter('the_content_feed', function($content) {
    if (has_post_thumbnail()) {
        $content = get_the_post_thumbnail(null, 'medium') . $content;
    }
    return $content;
});

// Добавляем автора и категории
add_filter('the_excerpt_rss', function($excerpt) {
    $categories = get_the_category();
    $cats = '';
    if ($categories) {
        $cats = 'Категории: ';
        foreach ($categories as $cat) {
            $cats .= $cat->name . ', ';
        }
        $cats = rtrim($cats, ', ');
    }
    
    return $excerpt . "\n\nАвтор: " . get_the_author() . "\n" . $cats;
});

// Создаем кастомный RSS фид
add_action('init', function() {
    add_feed('custom', function() {
        header('Content-Type: application/rss+xml');
        
        $posts = get_posts(['posts_per_page' => 20]);
        
        echo '<?xml version="1.0" encoding="UTF-8"?>';
        echo '<rss version="2.0">';
        echo '<channel>';
        echo '<title>' . get_bloginfo('name') . '</title>';
        echo '<link>' . home_url() . '</link>';
        echo '<description>' . get_bloginfo('description') . '</description>';
        
        foreach ($posts as $post) {
            echo '<item>';
            echo '<title>' . $post->post_title . '</title>';
            echo '<link>' . get_permalink($post->ID) . '</link>';
            echo '<description><![CDATA[' . $post->post_content . ']]></description>';
            echo '<pubDate>' . get_post_time('r', true, $post) . '</pubDate>';
            echo '</item>';
        }
        
        echo '</channel></rss>';
        exit;
    });
});

⚙️ 15. Системные уведомления и мониторинг

Вместо: плагины для мониторинга, сервисы uptime
Достаточно:

php
// Мониторинг критических ошибок register_shutdown_function(function() { $error = error_get_last(); if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { $to = get_option('admin_email'); $subject = 'КРИТИЧЕСКАЯ ОШИБКА на сайте ' . get_bloginfo('name'); $message = "Произошла критическая ошибка:\n\n"; $message .= "Тип: {$error['type']}\n"; $message .= "Сообщение: {$error['message']}\n"; $message .= "Файл: {$error['file']}\n"; $message .= "Строка: {$error['line']}\n"; $message .= "\nВремя: " . date('Y-m-d H:i:s'); wp_mail($to, $subject, $message); } }); // Мониторинг 404 ошибок add_action('template_redirect', function() { if (is_404()) { $url = $_SERVER['REQUEST_URI']; $referer = $_SERVER['HTTP_REFERER'] ?? ''; // Логируем только если это не бот $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $is_bot = preg_match('/bot|crawl|spider|slurp|mediapartners/i', $user_agent); if (!$is_bot) { $log = get_option('404_logs', []); $log[] = [ 'url' => $url, 'referer' => $referer, 'time' => current_time('mysql'), 'ip' => $_SERVER['REMOTE_ADDR'] ]; // Храним только последние 100 записей if (count($log) > 100) { $log = array_slice($log, -100); } update_option('404_logs', $log); } } }); // Еженедельный отчет на email add_action('wp', function() { if (!wp_next_scheduled('weekly_site_report')) { wp_schedule_event(time(), 'weekly', 'weekly_site_report'); } }); add_action('weekly_site_report', function() { $to = get_option('admin_email'); $subject = 'Еженедельный отчет сайта ' . get_bloginfo('name'); $report = "Отчет за неделю:\n\n"; $report .= "Всего записей: " . wp_count_posts('post')->publish . "\n"; $report .= "Всего страниц: " . wp_count_posts('page')->publish . "\n"; $report .= "Новые комментарии: " . wp_count_comments()->total_comments . "\n"; // 404 ошибки $not_founds = get_option('404_logs', []); if ($not_founds) { $report .= "\nПопулярные 404 ошибки:\n"; $urls = array_column($not_founds, 'url'); $counts = array_count_values($urls); arsort($counts); $i = 0; foreach ($counts as $url => $count) { if ($i++ >= 5) break; $report .= "{$url} - {$count} раз\n"; } } wp_mail($to, $subject, $report); });

📊 Сравнение: плагины vs код

Задача Плагин Код Экономия
Кеширование 5+ плагинов 15 строк 2-3 MB памяти
Безопасность 3-4 плагина 20 строк 5-7 запросов к БД
SEO 1-2 плагина 10 строк 1-2 секунды загрузки
Формы 1 плагин 15 строк 500 KB ресурсов
Итого 10-15 плагинов ~100 строк 30-50% скорости

⚡ Преимущества кода перед плагинами

Скорость:

  • 0 SQL запросов на запуск (у плагинов 2-10)

  • 0 дополнительных HTTP запросов (плагины грузят CSS/JS)

  • Меньше памяти (каждый плагин = 0.5-2MB)

Безопасность:

  • Меньше поверхностей атаки (каждый плагин = потенциальная дыра)

  • Полный контроль над кодом

  • Нет обновлений, которые могут сломать сайт

Производительность:

  • Нет конфликтов между плагинами

  • Лучшая совместимость с темой

  • Оптимизация под ваш конкретный случай

📋 Чек-лист: Что можно заменить прямо сейчас

Легко (5-10 минут):

  • Счетчик просмотров

  • Хлебные крошки

  • Похожие записи

  • Форма обратной связи

Средне (15-30 минут):

  • SEO-метатеги

  • Карта сайта

  • Ленивая загрузка

  • Защита от брутфорса

Сложно (1-2 часа):

  • Система кеширования

  • Полная защита

  • Мониторинг и уведомления

🚨 Важные предупреждения

Не заменяйте кодом:

  1. Сложные системы (интернет-магазины, форумы)

  2. Сторонние интеграции (платежные системы, доставка)

  3. Визуальные редакторы (Elementor, Divi)

  4. Сервисы с регулярными обновлениями (антиспам, аналитика)

Всегда используйте:

  1. Дочернюю тему — для functions.php

  2. Бэкапы — перед изменениями

  3. Тестовый сайт — для проверки

  4. Комментарии — в коде

🛠️ Как начать переход

Шаг 1: Аудит плагинов

sql
-- Посмотрите, какие плагины действительно нагружают сайт SELECT option_name, LENGTH(option_value) as size 
FROM wp_options 
WHERE option_name LIKE '%plugin%' ORDER BY size DESC;

Шаг 2: Замена по одному

  1. Деактивируйте один плагин

  2. Добавьте аналогичный код

  3. Протестируйте

  4. Удалите плагин

Шаг 3: Мониторинг результатов

php
// Добавьте в functions.php для мониторинга add_action('shutdown', function() { if (current_user_can('administrator')) { error_log('Memory: ' . memory_get_peak_usage() / 1024 / 1024 . ' MB'); error_log('Queries: ' . get_num_queries()); error_log('Time: ' . timer_stop() . ' sec'); } });

🎯 Итог

Десяток плагинов — это:

  • 20-30 дополнительных SQL запросов

  • 5-10 MB дополнительной памяти

  • 50+ дополнительных HTTP запросов

  • Риск конфликтов и уязвимостей

100 строк кода — это:

  • 0 дополнительных SQL запросов

  • < 1 MB дополнительной памяти

  • 0 дополнительных HTTP запросов

  • Полный контроль и оптимизация

Начните сегодня:

  1. Выберите один простой плагин

  2. Найдите его аналог в коде выше

  3. Замените

  4. Наслаждайтесь приростом скорости

Помните: каждый удаленный плагин — это +10% к скорости вашего сайта. А скорость — это деньги в интернете.