Code Monkey home page Code Monkey logo

laraload's Introduction

Goh Rhy Yan - Unsplash #y8CtjK0ej6A

Latest Version on Packagist License Coverage Status

Laraload

Effortlessly create a PHP 7.4 Preload script for your Laravel project.

Requirements

  • Laravel 7
  • PHP 7.4.3 or later
  • ext-opcache

The Opcache extension is not enforced by the package. Just be sure to enable it in your project's PHP main process.

Installation

Call composer and you're done.

composer require darkghosthunter/laraload

What is Preloading? What does this?

Preloading is a new feature for PHP 7.4 and Opcache. It "compiles" a list of files into memory, thus making the application code fast without warming up. For that to work, it needs to read a PHP script that uploads the files, at startup.

This package wraps the Preloader package that generates a preload file. Once it's generated, you can point the generated list into your php.ini:

opcache.preload = 'www/app/storage/preload.php';

Usage

By default, this package constantly recreates your preload script each 500 requests in storage/preload.php. That's it. But you want the details, don't you?

  1. A global terminable middleware checks for non-error response.
  2. Then it calls a custom Condition class.
  3. If the Condition evaluates to true, the script is generated.
  4. A PreloadCalledEvent is called with the generation status.

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="DarkGhostHunter\Laraload\LaraloadServiceProvider"

Let's check config array:

<?php

return [
    'condition' => \DarkGhostHunter\Laraload\Conditions\CountRequests::class,
    'output' =>  storage_path('preload.php'),
    'memory' => 32,
    'use_require' => false,
    'autoload' => base_path('vendor/autoload.php'),
];

Condition

This package comes with a simple condition class that returns true every 500 requests, which triggers the script generation.

You can define your own condition class to generate the Preload script. This will be called after the request is handled to the browser, and it will be resolved by the Service Container.

The condition is called the same way as a Controller action: as an invokable class or using Class@action notation.

<?php

return [
    'condition' => 'App\MyCustomCondition@handle',
];

Output

By default, the script is saved in your storage path, but you can change the filename and path to save it as long PHP has permissions to write on it.

<?php

return [
    'output' => '/var/www/preloads/my_preload.php',
];

Memory Limit

For most applications, 32MB is fine as a preload limit, but you may fine-tune it for your project specifically.

<?php

return [
    'memory' => 64,
];

Method

Opcache allows to preload files using require_once or opcache_compile_file().

From version 2.0, Laraload now uses opcache_compile_file() for better manageability on the files preloaded. Some unresolved links may output warnings, but nothing critical.

Using require_once will execute all files, resolving all the links (parent classes, traits, interfaces, etc.) before compiling it, and may output heavy errors on files that shouldn't be executed. Depending on your application, you may want to use one over the other.

If you plan use require_once, ensure you have set the correct path to the Composer Autoloader, since it will be used to resolve classes, among other files.

<?php

return [
    'use_require' => true,
    'autoload' => base_path('vendor/autoload.php'),
];

Include & Exclude directories

For better manageability, you can now append or exclude files from directories using the Symfony Finder, which is included in this package, to retrieve a list of files inside of them with better filtering options.

To do so, add an array of directories, or register a callback receiving a Symfony Finder instance to further filter which files you want to append or exclude. You can do this in your App Service Provider by using the Laravel facade (or injecting Laraload).

use Symfony\Component\Finder\Finder;
use Illuminate\Support\ServiceProvider;
use DarkGhostHunter\Laraload\Facades\Laraload;

class AppServiceProvider extends ServiceProvider
{
    // ...
    
    public function boot()
    {
        Laraload::append(function (Finder $find) {
            $find->in('www/app/vendor/name/package/src')->name('*.php');
        });
        
        Laraload::exclude(function (Finder $find) {
            $find->in('www/app/resources/views')->name('*.blade.php');
        });
    }
}

FAQ

  • The package returns errors when I used it!

Check you're using PHP 7.4.3 (critical), and Opcache is enabled. Also, check your storage directory is writable.

As a safe-bet, you can use the safe preloader script in darkghosthunter/preloader/helpers/safe-preloader.php and debug the error.

If you're sure this is an error by the package, open an issue with full details and stack trace. If it's a problem on the Preloader itself, issue it there.

  • Why I can't use something like php artisan laraload:generate instead? Like a Listener or Scheduler?

Opcache is not enabled when using PHP CLI. You must let the live application generate the list automatically on demand.

  • Does this excludes the package itself from the list?

It does not: since the underlying Preloader package may be not heavily requested, it doesn't matter if its excluded or not. The files in Laraload are also not excluded from the list, since these areneede to trigger the Preloader itself without hindering performance.

  • I activated Laraload but my application still doesn't feel snappy. What's wrong?

Laraload creates a preloading script, but doesn't load the script into Opcache. Once the script is generated, you must include it in your php.ini - currently there is no other way to do it. This will take effect only at PHP process startup.

If you still feel your app is slow, remember to benchmark your app, check your database queries and API calls, and queue expensive logic, among other things.

  • How the list is created?

Basically: the most hit files in descending order. Each file consumes memory, so the list is soft-cut when the files reach a given memory limit (32MB by default).

  • You said "soft-cut", why is that?

Each file is loaded using require_once, which also loads its other file links. If the last file is a class with links outside the list, these will be called to avoid unresolved dependencies.

  • Can I just put all the files in my project?

Yes, but including all the files of your application may have diminishing returns compared to, for example, only the most used. You can always benchmark your app yourself.

  • Can I use a Closure for my condition?

No, you must use your the default condition class or your own class, or use Class@method notation.

  • Can I deactivate the middleware? Or check only XXX status?

Nope. If you are looking for total control, use directly the Preloader package.

  • Does the middleware works on testing?

Nope. The middleware is not registered if the application is running under Unit Testing environment.

  • How can I know when a Preload script is successfully generated?

When the Preload script is called, you will receive a PreloadCalledEvent instance with the compilation status (true on success, false on failure). You can add a Listener to dispatch an email or a Slack notification.

If there is a bigger problem, your application logger will catch the exception.

  • Why now I need to use a callback to append/exclude files, instead of a simple array of files?

This new version uses Preloader 2, which offers greater flexibility to handle files inside a directory. This approach is incompatible with just issuing directly an array of files, but is more convenient in the long term. Considering that appending and excluding files mostly requires pin-point precision, it was decided to leave it as method calls for this kind of flexibility.

License

This package is licenced by the MIT License.

laraload's People

Contributors

darkghosthunter avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.