Performance Optimization
InspireCMS is designed to be fast and efficient, but as your site grows, optimizing performance becomes increasingly important. This guide covers various techniques and best practices to ensure your InspireCMS site remains responsive and speedy.
Performance Overview
Performance optimization in InspireCMS involves several key areas:
- Server Configuration: Optimizing your hosting environment
- Database Optimization: Ensuring efficient queries and indexing
- Application Caching: Leveraging various caching mechanisms
- Asset Optimization: Minimizing and efficiently serving static assets
- Content Delivery: Optimizing how content reaches users
- Frontend Performance: Making the user interface responsive
Server Optimization
PHP Configuration
Adjust PHP settings for optimal performance:
; php.ini optimizations
memory_limit = 256M
max_execution_time = 60
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 0
opcache.save_comments = 1
Web Server Configuration
Nginx Configuration
# nginx.conf optimizations
http {
# Enable gzip compression
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_types
application/javascript
application/json
application/xml
text/css
text/plain
text/xml;
# Cache control
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# PHP-FPM configuration
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
}
Apache Configuration
# .htaccess optimizations
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json
</IfModule>
Process Management
Configure PHP-FPM for better process management:
; php-fpm.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
Database Optimization
Query Optimization
Identify and optimize slow queries:
// Enable database query logging during development
\DB::connection()->enableQueryLog();
// After running operations, check the log
$queries = \DB::getQueryLog();
foreach ($queries as $query) {
\Log::debug($query['query'], [
'bindings' => $query['bindings'],
'time' => $query['time']
]);
}
Indexing Strategy
Add proper indexes to frequently queried columns:
// In a migration
Schema::table('cms_contents', function (Blueprint $table) {
// Index commonly filtered/sorted columns
$table->index(['document_type_id']);
$table->index(['parent_id']);
$table->index(['status']);
$table->index(['created_at']);
});
Query Caching
Cache frequent database queries:
// See the Caching section for query cache examples
Database Connection Pooling
Consider using database connection pooling for high-traffic sites:
// config/database.php
'mysql' => [
// ...
'pool' => [
'min_connections' => 1,
'max_connections' => 10,
'connection_timeout' => 10.0,
],
],
Application Optimization
Route Caching
Cache your application routes:
php artisan route:cache
Configuration Caching
Cache your application configuration:
php artisan config:cache
View Caching
Cache compiled Blade templates:
php artisan view:cache
Note: Clear these caches during development with the corresponding
clearcommands:php artisan route:clear,php artisan config:clear, andphp artisan view:clear.
Autoloader Optimization
Optimize Composer's autoloader in production:
composer install --optimize-autoloader --no-dev
Queue System
Use queues for time-consuming tasks to make your application more responsive:
// Process media optimization in the background
dispatch(new OptimizeMediaJob($mediaAsset));
// Generate sitemaps asynchronously
dispatch(new GenerateSitemapJob())->onQueue('low');
Configure a queue worker in production:
# Start queue worker (on server)
php artisan queue:work --queue=high,default,low --tries=3
# For use with Supervisor
[program:inspirecms-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/project/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/path/to/project/storage/logs/worker.log
Content Delivery Optimization
CDN Integration
Use a Content Delivery Network for assets:
// config/filesystems.php
'disks' => [
'cdn' => [
'driver' => 's3',
'key' => env('CDN_ACCESS_KEY_ID'),
'secret' => env('CDN_SECRET_ACCESS_KEY'),
'region' => env('CDN_DEFAULT_REGION'),
'bucket' => env('CDN_BUCKET'),
'url' => env('CDN_URL'),
],
],
// config/inspirecms.php
'media' => [
'media_library' => [
'disk' => 'cdn',
// other settings...
],
],
Lazy Loading
Implement lazy loading for images and heavy content:
<img
src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
data-src="{{ $image->getUrl() }}"
class="lazy-load"
alt="{{ $image->alt_text }}"
>
Include a JavaScript lazy loader:
document.addEventListener("DOMContentLoaded", function() {
let lazyImages = [].slice.call(document.querySelectorAll(".lazy-load"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
if (lazyImage.dataset.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
lazyImage.classList.remove("lazy-load");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
}
});
Image Optimization
Configure automatic image optimization:
// config/inspirecms.php
'media' => [
'image_optimization' => [
'enabled' => true,
'quality' => 80,
'convert_to_webp' => true,
'responsive_images' => [
'enabled' => true,
'widths' => [480, 768, 1280, 1920],
],
],
],
Frontend Performance
Asset Bundling
Use Laravel Mix or Vite to bundle and optimize assets:
// vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
},
},
},
});
Use in templates:
@vite(['resources/css/app.css', 'resources/js/app.js'])
Critical CSS
Inline critical CSS for faster initial rendering:
<head>
<!-- Inline critical styles for above-the-fold content -->
<style>
/* Critical CSS goes here */
.hero-section { /* ... */ }
.main-navigation { /* ... */ }
/* ... */
</style>
<!-- Defer non-critical CSS -->
<link rel="preload" href="{{ asset('css/main.css') }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ asset('css/main.css') }}"></noscript>
</head>
JavaScript Optimization
Load JavaScript efficiently:
<!-- Defer non-critical JavaScript -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- For critical functionality, use inline or async scripts -->
<script>
// Critical JS goes here
document.querySelector('body').classList.add('js-loaded');
</script>
Monitoring and Profiling
Laravel Telescope
Install Laravel Telescope for monitoring:
composer require laravel/telescope --dev
Configure in config/telescope.php:
'enabled' => env('TELESCOPE_ENABLED', false),
'middleware' => [
'web',
\Laravel\Telescope\Http\Middleware\Authorize::class,
],
'watchers' => [
\Laravel\Telescope\Watchers\QueryWatcher::class => [
'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
'slow' => 100,
],
// Other watchers...
],
Application Profiling
Use Laravel Debugbar for profiling:
composer require barryvdh/laravel-debugbar --dev
Performance Testing
Implement performance testing in your development workflow:
# Using k6 for load testing
k6 run -u 50 -d 30s tests/performance/load-homepage.js
Example test script:
// tests/performance/load-homepage.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export default function() {
let res = http.get('https://your-site.com/');
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(1);
}
Advanced Optimization Techniques
TTFB Optimization
Improve Time To First Byte with these techniques:
- Enable OPcache
- Use database connection pooling
- Optimize routing to reduce bootstrap overhead
- Cache rendered content for anonymous users
- Implement edge caching with CDN
Memory Optimization
Reduce memory usage in your application:
// Optimize collection handling for large datasets
$chunks = InspireCmsConfig::getContentModelClass()::cursor()->map(function ($content) {
// Process each item with minimal memory footprint
return $content->id;
});
Database Optimization Commands
Create commands to optimize database performance:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class OptimizeDatabaseCommand extends Command
{
protected $signature = 'inspirecms:optimize-database';
protected $description = 'Optimize database tables and indexes';
public function handle()
{
$this->info('Optimizing database tables...');
\DB::statement('OPTIMIZE TABLE cms_contents, cms_field_groupables, cms_content_paths');
$this->info('Analysis of content table');
$analysis = \DB::select('ANALYZE TABLE cms_contents');
$this->table(['Table', 'Operation', 'Msg Type', 'Msg Text'], $analysis);
return Command::SUCCESS;
}
}
Database Sharding
For very large sites, consider database sharding:
// config/database.php
'connections' => [
'mysql_content' => [
'driver' => 'mysql',
'host' => env('DB_CONTENT_HOST', '127.0.0.1'),
// other configuration...
],
'mysql_users' => [
'driver' => 'mysql',
'host' => env('DB_USERS_HOST', '127.0.0.1'),
// other configuration...
],
],
Update models to use specific connections:
// Example configuration for content model
namespace App\Models;
use SolutionForest\InspireCms\Models\Content as BaseContent;
class Content extends BaseContent
{
protected $connection = 'mysql_content';
}
Environment-Specific Optimizations
Development Environment
Optimize for developer experience:
// config/app.php for development
'debug' => true,
'cache' => false,
// .env.development
APP_DEBUG=true
DEBUGBAR_ENABLED=true
TELESCOPE_ENABLED=true
CACHE_DRIVER=array
Production Environment
Optimize for performance:
// config/app.php for production
'debug' => false,
'cache' => true,
// .env.production
APP_DEBUG=false
DEBUGBAR_ENABLED=false
TELESCOPE_ENABLED=false
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
CI/CD Optimization
Include performance checks in your CI/CD pipeline:
# .github/workflows/performance.yml
name: Performance Tests
on:
push:
branches: [ main ]
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install k6
run: |
curl -L https://github.com/loadimpact/k6/releases/download/v0.33.0/k6-v0.33.0-linux-amd64.tar.gz | tar xzf -
sudo cp k6-v0.33.0-linux-amd64/k6 /usr/local/bin/k6
- name: Run Performance Tests
run: k6 run tests/performance/load-tests.js
Best Practices Checklist
- Enable Production Mode: Always use production mode in live environments
- Cache Everything: Implement multiple cache layers
- Optimize Database: Index properly and monitor query performance
- Minimize HTTP Requests: Combine assets and use HTTP/2
- Optimize Images: Compress images and use responsive sizes
- Use CDN: Serve assets from a CDN
- Implement Queues: Move time-consuming tasks to the background
- Monitor Performance: Use tools to identify and address bottlenecks
- Optimize Critical Path: Focus on above-the-fold content delivery
- Regular Maintenance: Run periodic cleanup and optimization tasks
By applying these optimization techniques, your InspireCMS site will deliver content efficiently, providing a better experience for visitors and content editors alike.