Preload
Effortlessly create a PHP Preload Script for your Laravel project
Install / Use
/learn @Laragear/PreloadREADME
Preload
Dynamically preload your Laravel application.
This package generates a PHP preloading script from your Opcache statistics automatically. No need to hack your way in.
Become a sponsor
Your support allows me to keep this package free, up-to-date and maintainable. Alternatively, you can spread the word on social media!
Requirements
- PHP 8.3 or later
- Laravel 12 or later
- Opcache & Preloading enabled (
ext-opcache).
Installation
Require this using Composer into your project
composer require laragear/preload
[!NOTE]
This package doesn't require the
ext-opcacheextension to install. Just be sure to have it enabled in your deployment server.
What is Preloading? Does it make my app FAST?
PHP interpreter needs to read and compile each requested file in your project. When Opcache is enabled, it will keep interpreted files in memory instead of reading them again from the file system, which is miles faster.
Opcache's Preloading allows storing in memory a given list of files when the PHP process starts, before normal execution. This makes the application faster for first requests, as these files to read are already in memory. With JIT, these files are also compiled into byte-code, saving another step.
This package generates a file with a list containing the most accessed files of your application and a script that will load these files on startup. You can point the "loader" script into your php.ini:
opcache.preload_user = 'www-data'
opcache.preload = '/www/app/preload.php';
After that, the next time PHP starts, this list of files will be preloaded automatically.
[!NOTE]
If you're behind a shared server, preloading may be not available for your application. Normally, shared servers also share the same PHP process, and its configuration file (
php.ini) is not available for modification. Check your server if you're not sure if Laragear Preload should be installed.
Usage
By default, this package pushes a queued job each 10,000 requests, containing a limited list with the most accessed files of the application. This condition can be changed.
First, you should publish the stub script with the preload:stub Artisan command. By default, it will copy a stub preloader into the application root directory by default.
php artisan preload:stub
# Stub copied at [/www/app/preload.php]
#
# Remember to edit your [php.ini] file:
# opcache.preload = /www/app/preload.php;
This way, you can add the preload file path in your php.ini as instructed by the command.
opcache.preload = '/www/app/preload.php';
That's it. At the 10,000th request, the preloader stub will be replaced by a real preload script along with the list of files that should be warmed up by PHP at startup.
Custom condition
This package includes a simple condition callback: each 10,000 requests, generate a Preloading script.
If this condition is not enough for your application, or you require a custom condition, you can easily create a callback or even an invokable class with your own logic. The callable will be resolved by the application container, and run after the request has been sent to the browser.
Once you create the condition, register it through the condition() method of the Preloader facade. You can do this in your App\Providers\AppServiceProvider or bootstrap/app.php.
use Illuminate\Http\Request;
use Illuminate\Foundation\Application;
use Illuminate\Support\Lottery;
use Laragear\Preload\Facades\Preload;
return Application::configure()
->registered(function () {
Preload::condition(function (Request $request) {
if ($request->user()?->isAdmin()) {
return false;
}
return random_int(0, 100) === 50;
});
})->create();
You may also return a Illuminate\Support\Lottery instance for convenience, which is great for testing purposes.
use Illuminate\Support\Lottery;
use Laragear\Preload\Facades\Preload;
Preload::condition(function (Request $request) {
if ($request->user()?->isAdmin()) {
return false;
}
return Lottery::odds(2, 100);
});
Include and exclude
To include or exclude PHP files or entire directory paths from the Preload list, use the include() and exclude() methods from the Preload facade, respectively.
Both methods accept an array of glob patterns or a callback that receives the Symfony Finder for greater filtering options. On both cases, only .php files will be included in the list.
use Laragear\Preload\Facades\Preload;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Finder\Finder;
return Application::configure()
->booted(function () {
Preload::include(base_path('/services/**'));
Preload::exclude(function (Finder $find) {
$find->in(base_path('/temp/'))->contains('class ');
});
})
->create();
[!IMPORTANT]
Included files will be appended to the list. This means that exclusion logic will run first.
Excluding and including libraries
You can easily exclude or include entire libraries from your application by setting them at the extra.preload key of your composer.json, respectively.
The preload object should contain the library name as key, and false to exclude it or true to include. If you require fine-tuning, you can use an object with exclude and include files and a glob pattern for the file or files you wish to exclude or include, respectively. These patterns will be fed to the underlying Symfony Finder.
{
"extra": {
"preload": {
"laragear/meta": {
"exclude": ["src/Foo/*", "src/Bar/*/**"],
"include": "src/Request/*"
},
"charlesdp/builder": false
}
}
}
[!IMPORTANT]
Included libraries will be appended to the list. This means that exclusion logic will run first.
Configuration
Some people may not be happy with the "default" behaviour. Luckily, you can configure your own way to generate the script.
First publish the configuration file:
php artisan vendor:publish --provider="Laragear\Preload\PreloadServiceProvider"
Let's check the config array:
<?php
return [
'enabled' => env('PRELOAD_ENABLE'),
'project_only' => true,
'memory' => 32,
'job' => [
'connection' => env('PRELOAD_JOB_CONNECTION'),
'queue' => env('PRELOAD_JOB_QUEUE'),
],
'path' => base_path(),
'use_require' => false,
'autoload' => base_path('vendor/autoload.php'),
'ignore_not_found' => true,
];
Enable
return [
'env' => env('PRELOAD_ENABLE'),
];
By default, a global middleware is registered automatically on production environments. You can forcefully enable or disable this middleware using an environment variable set to true or false, respectively.
PRELOAD_ENABLE=true
Project Scope
return [
'project_only' => true,
];
Some PHP processes may be shared between multiple projects. To avoid preloading files outside the current project, this is set to true by default. Disabling it will allow preloading files regardless of the directory, even outside the project path.
Memory Limit
return [
'memory' => 32,
];
The memory limit, in MiB (aka "Windows MegaBytes"), of the List. Once this threshold is reached, no more scripts will be included in the list.
For most applications, 32MB is fine, but you may fine-tune it for your project specifically.
[!NOTE]
This is not Opcache memory limit, as its handled separately.
Job configuration
return [
'job' => [
'connection' => env('PRELOAD_JOB_CONNECTION'),
'queue' => env('PRELOAD_JOB_QUEUE'),
],
];
When the job receives the list to persist, it will be dispatched to the connection and queue set here. When null, the framework uses the defaults. You should use your .env file to set them:
PRELOAD_JOB_CONNECTION=redis
PRELOAD_JOB_QUEUE=low
Paths
return [
'path' => base_path(),
];
This set the directory path where the preloader files should be stored. By default, it uses your project root path.
If you change the directory path, ensure PHP has permissions to write on it. Whatever you place it, never do it in a public/accessible directory, like public or storage/app/public.
[!IMPORTANT]
Double-check your file permissions

