laravel-asset-cleaner maintained by tarunkorat
✨ Features
- 🔍 Smart Detection - Scans your entire Laravel project for unused assets
- 🛡️ Safe Deletion - Creates backups before removing any files
- 🎯 Selective Cleaning - Choose specific asset types (JS, CSS, images, fonts, etc.)
- 📊 Detailed Reports - See exactly what will be deleted and why
- 🔎 Debug Mode - Investigate why files are marked as used or unused
- ⚡ Fast Scanning - Efficiently processes large projects
- 🎨 Framework Agnostic - Works with Mix, Vite, plain webpack, and more
- 🔒 Protected Files - Never accidentally delete important files
- 📝 Strict Matching - Avoids false positives with intelligent pattern matching
- 🌟 Wildcard Support (New in v1.0.1) - Use wildcards in directory patterns
📋 Requirements
- PHP 8.2 or higher
- Laravel 9.x, 10.x, 11.x, or 12.x
- Composer
🚀 Installation
composer require tarunkorat/laravel-asset-cleaner
Publish Configuration
php artisan vendor:publish --tag=asset-cleaner-config
This creates config/asset-cleaner.php where you can customize settings.
📖 Usage
Basic Commands
Scan for Unused Assets
# Scan all asset types
php artisan assets:scan
# Scan specific types
php artisan assets:scan --type=js --type=css
php artisan assets:scan --type=img
# Show detailed information
php artisan assets:scan --details
# Output as JSON
php artisan assets:scan --json
Delete Unused Assets
# Dry run (preview what will be deleted)
php artisan assets:delete --dry-run
# Delete with confirmation
php artisan assets:delete
# Delete without confirmation
php artisan assets:delete --force
# Delete without backup
php artisan assets:delete --no-backup --force
# Delete specific types
php artisan assets:delete --type=js --type=css
Debug Mode
# Debug specific file
php artisan assets:debug resources/images/logo.png
# Show all found assets
php artisan assets:debug --show-all
# Show all reference patterns
php artisan assets:debug --show-refs
# Debug specific type
php artisan assets:debug --type=js --show-all
Example Workflow
# Step 1: Scan for unused assets
php artisan assets:scan
# Output:
# Found 15 unused asset(s):
# 📦 js (5 files)
# 📄 resources/js/old-component.js (2.5 KB)
# 📄 public/js/legacy-script.js (8.2 KB)
# 📦 css (4 files)
# 📄 resources/css/unused-styles.css (3.1 KB)
# 📦 img (6 files)
# 📄 public/images/old-logo.png (45 KB)
# Step 2: Preview deletion
php artisan assets:delete --dry-run
# Step 3: Delete unused assets
php artisan assets:delete
# Step 4: Verify backup created
# Backup location: storage/asset-cleaner-backup/2024-11-12_153045/
⚙️ Configuration
Edit config/asset-cleaner.php:
return [
// Specify which asset types to clean by default
'clean_types' => 'all', // or ['js', 'css', 'img']
// Enable strict matching (recommended)
'strict_matching' => true,
// Define asset types and their locations
'asset_types' => [
'js' => [
'directories' => [
'resources/js',
'public/js',
'public/js/*', // ✨ NEW: Wildcard support
],
'extensions' => ['js', 'jsx', 'ts', 'tsx', 'vue', 'mjs'],
],
'css' => [
'directories' => [
'resources/css',
'resources/sass',
'public/css',
'public/css/*', // ✨ NEW: Scans css/vendor, css/admin, etc.'
],
'extensions' => ['css', 'scss', 'sass', 'less'],
],
'img' => [
'directories' => [
'resources/images',
'public/images',
'public/assets/**', // ✨ NEW: Recursive wildcard
],
'extensions' => ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'ico'],
],
// ... more types
],
// Directories to scan for asset references
'scan_directories' => ['app', 'resources/views', 'resources/js', 'routes'],
// Files that should never be deleted
'protected_files' => [
'resources/js/app.js',
'resources/css/app.css',
],
// Backup settings
'backup_directory' => storage_path('asset-cleaner-backup'),
'create_backup' => true,
];
🔍 How It Works
Detection Process
- Scans Asset Directories - Finds all assets in configured directories
- Searches for References - Looks for asset usage in:
- Blade templates (
asset(),<img src>,<script>,<link>) - JavaScript files (imports, requires, dynamic imports)
- CSS files (
url(),@import, background images) - PHP controllers (
Image::make(),public_path(),Storage::url()) - Vue/React components (import statements, src attributes)
- Build configs (webpack.mix.js, vite.config.js, package.json)
- Blade templates (
- Strict Matching - Only matches complete filenames with extensions
- Safe Deletion - Creates timestamped backups before removal
Wildcard Directory Patterns (New in v1.0.1)
You can now use wildcard patterns in your directory configuration for more flexible asset scanning.
Single Level Wildcard (*) Single Level Wildcard (*)
'directories' => [
'public/css/*', // Scans: public/css/vendor, public/css/admin, public/css/themes
]
Example structure:
public/css/
├── app.css ✅ Scanned
├── vendor/
│ └── bootstrap.css ✅ Scanned
└── admin/
└── style.css ✅ Scanned
**Recursive Wildcard () Scans the directory and ALL subdirectories recursively:
'directories' => [
'public/assets/**', // Scans everything under public/assets
]
Example structure:
public/assets/
├── css/
│ ├── app.css ✅ Scanned
│ └── vendor/
│ └── bootstrap.css ✅ Scanned
├── js/
│ └── app.js ✅ Scanned
└── images/
└── logo.png ✅ Scanned
What Gets Detected
✅ These patterns are detected:
// Blade templates
<img src="{{ asset('images/logo.png') }}">
<script src="{{ mix('js/app.js') }}"></script>
// JavaScript
import Logo from './images/logo.png';
require('./components/Header.vue');
// CSS
background-image: url('../images/banner.jpg');
@import 'components/button.css';
// PHP Controllers
$image = Image::make(public_path('images/product.jpg'));
return asset('images/logo.png');
❌ False positives avoided:
- File named
error.svgwon't match word "error" in code test.jswon't match variable named "test"- Strict boundary checking prevents partial matches
🛡️ Safety Features
- ✅ Automatic Backups - All deleted files are backed up with timestamps
- ✅ Protected Files - Important files (app.js, app.css) are never deleted
- ✅ Dry Run Mode - Preview changes before applying them
- ✅ Confirmation Prompts - Asks for confirmation before deletion
- ✅ Verification - Checks if files were actually deleted
- ✅ Error Logging - Failed deletions are logged for review
🎯 Use Cases
Clean Up After Refactoring
# After removing old components
php artisan assets:scan --type=js
php artisan assets:delete --type=js --dry-run
Optimize Images
# Find unused images
php artisan assets:scan --type=img
php artisan assets:delete --type=img
CI/CD Integration
# In your deployment script
php artisan assets:scan --json > unused-assets-report.json
Before Production Deploy
# Clean up everything
php artisan assets:scan
php artisan assets:delete --force
🐛 Troubleshooting
Files Not Being Detected as Unused
# Debug specific file
php artisan assets:debug resources/js/MyComponent.vue
# This will show:
# - Where the file is located
# - What references it (if any)
# - Why it's marked as used/unused
Files Won't Delete
Common causes:
- File permissions (run as administrator on Windows)
- File is open in an editor
- Antivirus blocking deletion
Solution:
# Check what failed
# Check Laravel logs: storage/logs/laravel.log
# Try with elevated permissions (Windows)
# Run PowerShell as Administrator
php artisan assets:delete --force
False Positives
If files are incorrectly marked as used:
// config/asset-cleaner.php
'strict_matching' => true, // Ensure this is enabled
Restore from Backup
# Backups are in storage/asset-cleaner-backup/
# Each run creates a timestamped folder
# To restore:
cp -r storage/asset-cleaner-backup/2024-11-12_153045/* ./
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Development Setup
# Clone the repository
git clone https://github.com/tarunkorat/laravel-asset-cleaner.git
# Install dependencies
composer install
📝 Changelog
Please see CHANGELOG.md for recent changes.
🔒 Security
If you discover any security issues, please email tarunkorat336@gmail.com instead of using the issue tracker.
📄 License
The MIT License (MIT). Please see LICENSE for more information.
💖 Support
If this package helped you, please consider:
- ⭐ Starring the repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- 📖 Improving documentation