Azwar's Blog

Website Performance Optimization: Speed Up WordPress and Laravel Applications

November 10, 2024 (8mo ago)WordPress

Hi everyone! I'm Azwar, a WordPress and Laravel developer with a passion for performance optimization. In this comprehensive guide, I'll share essential techniques for optimizing website performance in both WordPress and Laravel applications. Website speed is crucial for user experience and SEO rankings.

Website Performance Optimization: Speed Up Applications
Website Performance Optimization: Speed Up Applications

Website performance directly impacts user experience, conversion rates, and search engine rankings. A fast website not only keeps users engaged but also improves your site's visibility in search results. Let's explore various optimization techniques for both WordPress and Laravel applications.

Understanding Performance Metrics

Key Performance Indicators

  1. Page Load Time: Total time to load a page
  2. Time to First Byte (TTFB): Server response time
  3. First Contentful Paint (FCP): When first content appears
  4. Largest Contentful Paint (LCP): When main content loads
  5. Cumulative Layout Shift (CLS): Visual stability
  6. First Input Delay (FID): Interactivity responsiveness

Performance Testing Tools

  • Google PageSpeed Insights: Comprehensive performance analysis
  • GTmetrix: Detailed performance reports
  • WebPageTest: Advanced testing with multiple locations
  • Lighthouse: Chrome DevTools performance auditing

WordPress Performance Optimization

1. WordPress Caching Implementation

<?php /** * Plugin Name: Advanced WordPress Caching * Description: Custom caching solution for WordPress * Version: 1.0.0 * Author: Azwar */ class Advanced_Caching { private $cache_group = 'advanced_cache'; private $cache_expiry = 3600; // 1 hour public function __construct() { add_action('init', [$this, 'init_cache']); add_action('wp_footer', [$this, 'cache_page']); add_filter('the_content', [$this, 'cache_content']); } public function init_cache() { if (!wp_cache_get('cache_initialized', $this->cache_group)) { wp_cache_set('cache_initialized', true, $this->cache_group, 86400); } } public function cache_page() { if (is_user_logged_in() || is_admin()) { return; } $cache_key = $this->generate_cache_key(); $page_content = ob_get_contents(); if ($page_content) { wp_cache_set($cache_key, $page_content, $this->cache_group, $this->cache_expiry); } } public function cache_content($content) { if (is_user_logged_in() || is_admin()) { return $content; } $cache_key = 'content_' . md5($content); $cached_content = wp_cache_get($cache_key, $this->cache_group); if ($cached_content === false) { wp_cache_set($cache_key, $content, $this->cache_group, $this->cache_expiry); return $content; } return $cached_content; } private function generate_cache_key() { $key_parts = [ 'page', get_the_ID(), is_home() ? 'home' : '', is_single() ? 'single' : '', is_page() ? 'page' : '', $_SERVER['REQUEST_URI'] ?? '', ]; return md5(implode('_', array_filter($key_parts))); } public function clear_cache() { wp_cache_flush_group($this->cache_group); } } new Advanced_Caching();

2. WordPress Database Optimization

<?php class Database_Optimizer { public function __construct() { add_action('wp_scheduled_delete', [$this, 'cleanup_database']); add_action('admin_menu', [$this, 'add_admin_menu']); } public function cleanup_database() { global $wpdb; // Remove post revisions $wpdb->query(" DELETE FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_date < DATE_SUB(NOW(), INTERVAL 30 DAY) "); // Remove auto-drafts $wpdb->query(" DELETE FROM {$wpdb->posts} WHERE post_status = 'auto-draft' AND post_date < DATE_SUB(NOW(), INTERVAL 7 DAY) "); // Remove spam comments $wpdb->query(" DELETE FROM {$wpdb->comments} WHERE comment_approved = 'spam' "); // Remove orphaned post meta $wpdb->query(" DELETE pm FROM {$wpdb->postmeta} pm LEFT JOIN {$wpdb->posts} p ON pm.post_id = p.ID WHERE p.ID IS NULL "); // Optimize tables $tables = $wpdb->get_results("SHOW TABLES LIKE '{$wpdb->prefix}%'"); foreach ($tables as $table) { $table_name = array_values((array) $table)[0]; $wpdb->query("OPTIMIZE TABLE {$table_name}"); } } public function optimize_queries() { // Add database indexes global $wpdb; $wpdb->query(" CREATE INDEX IF NOT EXISTS idx_posts_status_date ON {$wpdb->posts} (post_status, post_date DESC) "); $wpdb->query(" CREATE INDEX IF NOT EXISTS idx_comments_post_status ON {$wpdb->comments} (comment_post_ID, comment_approved) "); } } new Database_Optimizer();

3. WordPress Asset Optimization

<?php class Asset_Optimizer { public function __construct() { add_action('wp_enqueue_scripts', [$this, 'optimize_assets'], 999); add_filter('script_loader_tag', [$this, 'add_async_defer'], 10, 3); add_action('wp_head', [$this, 'preload_critical_assets']); } public function optimize_assets() { // Dequeue unnecessary scripts if (!is_admin()) { wp_dequeue_script('wp-embed'); wp_deregister_script('wp-embed'); } // Combine and minify CSS $this->combine_css_files(); // Combine and minify JavaScript $this->combine_js_files(); } public function combine_css_files() { global $wp_styles; $css_files = []; $combined_css = ''; foreach ($wp_styles->queue as $handle) { $src = $wp_styles->registered[$handle]->src; if (strpos($src, 'http') === 0) { $css_content = file_get_contents($src); if ($css_content) { $combined_css .= $this->minify_css($css_content); } } } if ($combined_css) { $upload_dir = wp_upload_dir(); $css_file = $upload_dir['basedir'] . '/combined-' . md5($combined_css) . '.css'; file_put_contents($css_file, $combined_css); wp_enqueue_style('combined-css', $upload_dir['baseurl'] . '/combined-' . md5($combined_css) . '.css'); } } public function combine_js_files() { global $wp_scripts; $js_files = []; $combined_js = ''; foreach ($wp_scripts->queue as $handle) { $src = $wp_scripts->registered[$handle]->src; if (strpos($src, 'http') === 0) { $js_content = file_get_contents($src); if ($js_content) { $combined_js .= $this->minify_js($js_content); } } } if ($combined_js) { $upload_dir = wp_upload_dir(); $js_file = $upload_dir['basedir'] . '/combined-' . md5($combined_js) . '.js'; file_put_contents($js_file, $combined_js); wp_enqueue_script('combined-js', $upload_dir['baseurl'] . '/combined-' . md5($combined_js) . '.js', [], null, true); } } private function minify_css($css) { // Remove comments $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css); // Remove whitespace $css = str_replace(["\r\n", "\r", "\n", "\t"], '', $css); $css = preg_replace('/\s+/', ' ', $css); return trim($css); } private function minify_js($js) { // Basic JavaScript minification $js = preg_replace('/\/\*.*?\*\//s', '', $js); $js = preg_replace('/\/\/.*$/m', '', $js); $js = preg_replace('/\s+/', ' ', $js); return trim($js); } public function add_async_defer($tag, $handle, $src) { if (in_array($handle, ['jquery', 'wp-embed'])) { return $tag; } return str_replace('<script ', '<script async defer ', $tag); } public function preload_critical_assets() { echo '<link rel="preload" href="' . get_stylesheet_uri() . '" as="style" onload="this.onload=null;this.rel=\'stylesheet\'">'; echo '<noscript><link rel="stylesheet" href="' . get_stylesheet_uri() . '"></noscript>'; } } new Asset_Optimizer();

Laravel Performance Optimization

1. Laravel Caching Strategies

<?php // app/Services/CacheService.php class CacheService { private $cache; public function __construct() { $this->cache = Cache::store('redis'); } public function remember($key, $callback, $ttl = 3600) { return $this->cache->remember($key, $ttl, $callback); } public function rememberForever($key, $callback) { return $this->cache->rememberForever($key, $callback); } public function tags($names) { return $this->cache->tags($names); } public function flush() { return $this->cache->flush(); } } // app/Http/Controllers/PostController.php class PostController extends Controller { private $cacheService; public function __construct(CacheService $cacheService) { $this->cacheService = $cacheService; } public function index(Request $request) { $cacheKey = 'posts_' . md5($request->fullUrl()); return $this->cacheService->remember($cacheKey, 1800, function () use ($request) { $query = Post::with(['author', 'categories', 'tags']) ->where('status', 'published'); if ($request->has('search')) { $query->where('title', 'like', '%' . $request->search . '%'); } return $query->orderBy('created_at', 'desc') ->paginate($request->get('per_page', 15)); }); } public function show(Post $post) { $cacheKey = 'post_' . $post->id; return $this->cacheService->remember($cacheKey, 3600, function () use ($post) { return $post->load(['author', 'categories', 'tags', 'comments']); }); } }

2. Laravel Database Optimization

<?php // app/Models/Post.php class Post extends Model { protected $fillable = [ 'title', 'content', 'excerpt', 'author_id', 'status' ]; // Eager loading relationships protected $with = ['author']; // Cache frequently accessed data public function getCachedCommentsCountAttribute() { return Cache::remember("post_{$this->id}_comments_count", 3600, function () { return $this->comments()->count(); }); } public function getCachedLikesCountAttribute() { return Cache::remember("post_{$this->id}_likes_count", 3600, function () { return $this->likes()->count(); }); } // Optimize queries with scopes public function scopePublished($query) { return $query->where('status', 'published'); } public function scopePopular($query) { return $query->withCount('likes') ->orderBy('likes_count', 'desc'); } public function scopeRecent($query) { return $query->orderBy('created_at', 'desc'); } } // Database migrations for optimization class CreateOptimizedIndexes extends Migration { public function up() { Schema::table('posts', function (Blueprint $table) { $table->index(['status', 'created_at']); $table->index(['author_id', 'status']); $table->fullText(['title', 'content']); }); Schema::table('comments', function (Blueprint $table) { $table->index(['post_id', 'approved']); $table->index('created_at'); }); } public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropIndex(['status', 'created_at']); $table->dropIndex(['author_id', 'status']); $table->dropFullText(['title', 'content']); }); Schema::table('comments', function (Blueprint $table) { $table->dropIndex(['post_id', 'approved']); $table->dropIndex('created_at'); }); } }

3. Laravel Queue and Job Optimization

<?php // app/Jobs/ProcessHeavyTask.php class ProcessHeavyTask implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $timeout = 300; public $tries = 3; private $data; public function __construct($data) { $this->data = $data; } public function handle() { // Process heavy task in background $this->processData($this->data); // Cache results Cache::put('processed_data_' . md5(serialize($this->data)), $result, 3600); } private function processData($data) { // Heavy processing logic sleep(5); // Simulate heavy processing } } // app/Console/Commands/OptimizeDatabase.php class OptimizeDatabase extends Command { protected $signature = 'db:optimize'; protected $description = 'Optimize database tables'; public function handle() { $tables = DB::select('SHOW TABLES'); foreach ($tables as $table) { $tableName = array_values((array) $table)[0]; DB::statement("OPTIMIZE TABLE {$tableName}"); $this->info("Optimized table: {$tableName}"); } $this->info('Database optimization completed!'); } }

4. Laravel Frontend Optimization

<?php // config/app.php 'debug' => env('APP_DEBUG', false), 'env' => env('APP_ENV', 'production'), // webpack.mix.js const mix = require('laravel-mix'); mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css') .version() .sourceMaps() .options({ processCssUrls: false, postCss: [ require('autoprefixer'), require('cssnano')({ preset: 'default', }) ] }); // app/Http/Middleware/AssetOptimization.php class AssetOptimization { public function handle($request, Closure $next) { $response = $next($request); if ($response instanceof Response) { $content = $response->getContent(); // Minify HTML $content = $this->minifyHtml($content); // Add security headers $response->headers->set('X-Content-Type-Options', 'nosniff'); $response->headers->set('X-Frame-Options', 'SAMEORIGIN'); $response->headers->set('X-XSS-Protection', '1; mode=block'); $response->setContent($content); } return $response; } private function minifyHtml($html) { $search = [ '/\>[^\S ]+/s', // strip whitespaces after tags, except space '/[^\S ]+\</s', // strip whitespaces before tags, except space '/(\s)+/s' // shorten multiple whitespace sequences ]; $replace = [ '>', '<', '\\1' ]; return preg_replace($search, $replace, $html); } }

Advanced Performance Techniques

1. CDN Implementation

<?php // WordPress CDN configuration function configure_cdn() { if (!is_admin()) { // Replace local URLs with CDN URLs add_filter('wp_get_attachment_url', function($url) { return str_replace(home_url(), 'https://cdn.yourdomain.com', $url); }); // Add CDN for assets add_filter('style_loader_src', function($src) { return str_replace(home_url(), 'https://cdn.yourdomain.com', $src); }); add_filter('script_loader_src', function($src) { return str_replace(home_url(), 'https://cdn.yourdomain.com', $src); }); } } // Laravel CDN configuration // config/filesystems.php 'disks' => [ 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), ], ], // Use CDN for asset URLs Storage::disk('s3')->url('path/to/file.jpg');

2. Image Optimization

<?php // WordPress image optimization class Image_Optimizer { public function optimize_images() { add_filter('wp_handle_upload', [$this, 'compress_uploaded_image']); add_filter('wp_generate_attachment_metadata', [$this, 'generate_webp_versions']); } public function compress_uploaded_image($file) { if (strpos($file['type'], 'image/') === 0) { $this->compress_image($file['file']); } return $file; } public function compress_image($file_path) { $image = imagecreatefromstring(file_get_contents($file_path)); if ($image) { imagejpeg($image, $file_path, 85); // 85% quality imagedestroy($image); } } public function generate_webp_versions($metadata) { if (function_exists('imagewebp')) { $upload_dir = wp_upload_dir(); $file_path = $upload_dir['basedir'] . '/' . $metadata['file']; $webp_path = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $file_path); $this->convert_to_webp($file_path, $webp_path); } return $metadata; } private function convert_to_webp($source, $destination) { $image = imagecreatefromstring(file_get_contents($source)); if ($image) { imagewebp($image, $destination, 85); imagedestroy($image); } } } // Laravel image optimization // composer require intervention/image use Intervention\Image\Facades\Image; class ImageService { public function optimize($file, $quality = 85) { $image = Image::make($file); // Resize if too large if ($image->width() > 1920) { $image->resize(1920, null, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); } // Optimize quality $image->save($file, $quality); return $file; } public function generateWebp($file) { $image = Image::make($file); $webpPath = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $file); $image->save($webpPath, 85, 'webp'); return $webpPath; } }

Performance Monitoring

1. WordPress Performance Monitoring

<?php class Performance_Monitor { public function __construct() { add_action('wp_footer', [$this, 'log_performance']); add_action('admin_menu', [$this, 'add_performance_menu']); } public function log_performance() { $load_time = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']; $memory_usage = memory_get_peak_usage(true); $performance_data = [ 'load_time' => $load_time, 'memory_usage' => $memory_usage, 'url' => $_SERVER['REQUEST_URI'], 'timestamp' => current_time('mysql'), ]; // Log to database or file $this->save_performance_log($performance_data); } private function save_performance_log($data) { global $wpdb; $wpdb->insert( $wpdb->prefix . 'performance_logs', $data, ['%f', '%d', '%s', '%s'] ); } public function get_performance_stats() { global $wpdb; $stats = $wpdb->get_results(" SELECT AVG(load_time) as avg_load_time, MAX(load_time) as max_load_time, AVG(memory_usage) as avg_memory, COUNT(*) as total_requests FROM {$wpdb->prefix}performance_logs WHERE timestamp > DATE_SUB(NOW(), INTERVAL 24 HOUR) "); return $stats[0] ?? null; } } new Performance_Monitor();

2. Laravel Performance Monitoring

<?php // app/Providers/AppServiceProvider.php public function boot() { // Monitor database queries if (config('app.debug')) { DB::listen(function ($query) { Log::channel('performance')->info('Query executed', [ 'sql' => $query->sql, 'bindings' => $query->bindings, 'time' => $query->time, ]); }); } // Monitor response times app('router')->matched(function ($route, $request) { $startTime = microtime(true); app()->terminating(function () use ($startTime, $route) { $endTime = microtime(true); $duration = ($endTime - $startTime) * 1000; Log::channel('performance')->info('Route executed', [ 'route' => $route->getName(), 'duration' => $duration, 'memory' => memory_get_peak_usage(true), ]); }); }); } // config/logging.php 'channels' => [ 'performance' => [ 'driver' => 'daily', 'path' => storage_path('logs/performance.log'), 'level' => 'info', 'days' => 30, ], ],

Best Practices for Performance Optimization

  1. Use Caching Strategically: Implement multiple layers of caching
  2. Optimize Database Queries: Use proper indexing and query optimization
  3. Minimize HTTP Requests: Combine and compress assets
  4. Use CDN: Distribute content globally
  5. Optimize Images: Compress and use modern formats
  6. Implement Lazy Loading: Load content as needed
  7. Monitor Performance: Track key metrics regularly
  8. Use Compression: Enable Gzip/Brotli compression
  9. Optimize Critical Path: Prioritize above-the-fold content
  10. Regular Maintenance: Clean up and optimize regularly

Conclusion

Performance optimization is an ongoing process that requires monitoring, testing, and continuous improvement. By implementing these techniques in your WordPress and Laravel applications, you can significantly improve website speed and user experience.

Remember to always test performance changes in a staging environment and monitor the impact on your live site.

Additional Resources

Comments