Caches responses as static files on disk for lightning fast page loads.

Related tags

Laravel page-cache
Overview

Laravel Page Cache

Build Status Latest Stable Version Total Downloads License

This package allows you to easily cache responses as static files on disk for lightning fast page loads.


Introduction

While static site builders such as Jekyll and Jigsaw are extremely popular these days, dynamic PHP sites still offer a lot of value even for a site that is mostly static. A proper PHP site allows you to easily add dynamic functionality wherever needed, and also means that there's no build step involved in pushing updates to the site.

That said, for truly static pages on a site there really is no reason to have to boot up a full PHP app just to serve a static page. Serving a simple HTML page from disk is infinitely faster and less taxing on the server.

The solution? Full page caching.

Using the middleware included in this package, you can selectively cache the response to disk for any given request. Subsequent calls to the same page will be served directly as a static HTML page!

Installation

Install the page-cache package with composer:

$ composer require silber/page-cache

Service Provider

Note: If you're using Laravel 5.5+, the service provider will be registered automatically. You can simply skip this step entirely.

Open config/app.php and add a new item to the providers array:

Silber\PageCache\LaravelServiceProvider::class,

Middleware

Open app/Http/Kernel.php and add a new item to the web middleware group:

protected $middlewareGroups = [
    'web' => [
        \Silber\PageCache\Middleware\CacheResponse::class,
        /* ... keep the existing middleware here */
    ],
];

The middleware is smart enough to only cache responses with a 200 HTTP status code, and only for GET requests.

If you want to selectively cache only specific requests to your site, you should instead add a new mapping to the routeMiddleware array:

protected $routeMiddleware = [
    'page-cache' => \Silber\PageCache\Middleware\CacheResponse::class,
    /* ... keep the existing mappings here */
];

Once registered, you can then use this middleware on individual routes.

URL rewriting

In order to serve the static files directly once they've been cached, you need to properly configure your web server to check for those static files.

  • For nginx:

    Update your location block's try_files directive to include a check in the page-cache directory:

    location = / {
        try_files /page-cache/pc__index__pc.html /index.php?$query_string;
    }
    
    location / {
        try_files $uri $uri/ /page-cache/$uri.html /page-cache/$uri.json /index.php?$query_string;
    }
  • For apache:

    Open public/.htaccess and add the following before the block labeled Handle Front Controller:

    # Serve Cached Page If Available...
    RewriteCond %{REQUEST_URI} ^/?$
    RewriteCond %{DOCUMENT_ROOT}/page-cache/pc__index__pc.html -f
    RewriteRule .? page-cache/pc__index__pc.html [L]
    RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.html -f
    RewriteRule . page-cache%{REQUEST_URI}.html [L]
    RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.json -f
    RewriteRule . page-cache%{REQUEST_URI}.json [L]

Ignoring the cached files

To make sure you don't commit your locally cached files to your git repository, add this line to your .gitignore file:

/public/page-cache

Usage

Using the middleware

Note: If you've added the middleware to the global web group, then all successful GET requests will automatically be cached. No need to put the middleware again directly on the route.

If you instead registered it as a route middleware, you should use the middleware on whichever routes you want to be cached.

To cache the response of a given request, use the page-cache middleware:

Route::middleware('page-cache')->get('posts/{slug}', 'PostController@show');

Every post will now be cached to a file under the public/page-cache directory, closely matching the URL structure of the request. All subsequent requests for this post will be served directly from disk, never even hitting your app!

Clearing the cache

Since the responses are cached to disk as static files, any updates to those pages in your app will not be reflected on your site. To update pages on your site, you should clear the cache with the following command:

php artisan page-cache:clear

As a rule of thumb, it's good practice to add this to your deployment script. That way, whenever you push an update to your site the page cache will automatically be cleared.

If you're using Forge's Quick Deploy feature, you should add this line to the end of your Deploy Script. This'll ensure that the cache is cleared whenever you push an update to your site.

You may optionally pass a URL slug to the command, to only delete the cache for a specific page:

php artisan page-cache:clear {slug}

To clear everything under a given path, use the --recursive flag:

php artisan page-cache:clear {slug} --recursive

For example, imagine you have a category resource under /categories, with the following cached pages:

  • /categories/1
  • /categories/2
  • /categories/5

To clear the cache for all categories, use --recursive with the categories path:

php artisan page-cache:clear categories --recursive

Customizing what to cache

By default, all GET requests with a 200 HTTP response code are cached. If you want to change that, create your own middleware that extends the package's base middleware, and override the shouldCache method with your own logic.

  1. Run the make:middleware Artisan command to create your middleware file:

    php artisan make:middleware CacheResponse
    
  2. Replace the contents of the file at app/Http/Middleware/CacheResponse.php with this:

    <?php
    
    namespace App\Http\Middleware;
    
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Silber\PageCache\Middleware\CacheResponse as BaseCacheResponse;
    
    class CacheResponse extends BaseCacheResponse
    {
        protected function shouldCache(Request $request, Response $response)
        {
            // In this example, we don't ever want to cache pages if the
            // URL contains a query string. So we first check for it,
            // then defer back up to the parent's default checks.
            if ($request->getQueryString()) {
                return false;
            }
    
            return parent::shouldCache($request, $response);
        }
    }
  3. Finally, update the middleware references in your app/Http/Kernel.php file, to point to your own middleware.

License

The Page Cache package is open-sourced software licensed under the MIT license.

Comments
  • How to cache for XML file

    How to cache for XML file

    I can cache JSON and HTML file but How can I cache XML files which are used for sitemaps?

    Function I got:

        protected function getFileExtension($response)
        {
            if ($response instanceof JsonResponse) {
                return '.json';
            }
            return '.html';
        }
    

    XML File Format:

    `

      <loc>http://www.example.com/</loc>
    
      <lastmod>2005-01-01</lastmod>
    
      <changefreq>monthly</changefreq>
    
      <priority>0.8</priority>
    

    `

    enhancement 
    opened by theankitjais 8
  • Doesn't work with / path and Apache

    Doesn't work with / path and Apache

    It doesn't seem to work with a root path (/) route and Apache. The static html file is created with the file name ".html" (and recreated on every request), but I can see that PHP is responding instead of only Apache. The route "/en" is working as expected.

    This is my route:

    Route::get('/{locale?}', function ($locale = 'sv') {
        return view('start')->with('locale', $locale);
    })->middleware(['page-cache']);
    

    Otherwise, great package :)

    opened by eminos 6
  •  Does not work try_files for main page in nginx

    Does not work try_files for main page in nginx

    Hello. I use nginx and laravel 5.4. Html file pc__index__pc.html is created in page-cache folder, but nginx does not see it.

    My nginx config:

         location / {
    		try_files $uri $uri/ /page-cache/$uri.html /index.php?$query_string;
    	}
    	
    	location ~ \..*/.*\.php$ {
    		# For super-cool-hackers
    		return 403;
    	}
    	
    	location ~ \.php$ {
    		try_files $uri /index.php =404;
    		fastcgi_pass 127.0.0.1:9000;
    		fastcgi_split_path_info ^(.+\.php)(/.*)$;
    		fastcgi_index index.php;
    		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    		include fastcgi_params;
    		fastcgi_read_timeout 300;
    	}
    

    Tell me please, what is wrong?

    opened by mezhevikin 5
  • Query Strings

    Query Strings

    Hello,

    I notice that issue #25 was closed as query strings do not always indicate a unique endpoint, but I believe that it's still worth enabling caching in these instances. Of course, additional disk space is required.

    There are some security considerations to prevent an attacker filling the disk by trying endpoints that will return a 200 code, but this should probably be handled by a WAF anyway if it's a concern (my feeling is that an attacker will DoS the site before they fill the disk).

    Would you be open to a pull request that enables caching of query strings if the functionality can be enabled via env configuration?

    My intention would be to clear all variants of a page (e.g. /mypage, /mypage?page=1, /mypage?page=2 etc) when the request is made to purge /mypage so there would be no need to key based on the query string.

    I would propose saving files in a format similar to

    mypage[q_].html
    mypage[q_page=1].html
    

    which is fairly simple for the webserver to match on.

    I want this feature as I feel the benefits of serving static content, particularly on an API response have the potential to greatly improve user experience as well as providing a significant energy-saving benefit when bypassing PHP and reducing the need to scale.

    If this is something you remain opposed to I'll look at other solutions.

    Thanks for providing this to the community, it's an excellent package.

    Regards

    opened by robballantyne 4
  • Enable .json file extension for json responses

    Enable .json file extension for json responses

    To automatically set the correct content-type for application/json responses, check if the response is a JsonResponse and if so, create a .json file instead of a .html file.

    I didn't write a test since I didn't know where to start to be honest.

    It is not perfect since the ending "json" is hardcoded but in the future, the determineFileExtension method could be extended if needed.

    Also, the forget method is not the most elegant with trying to delete either a .html or a .json file. If you have a better idea on how to solve that, please let me know and I'll try to rewrite it. I've chosen this way since at least in my applications, it's always either a html or json response which would benefit the most from the caching.

    Cheers!

    opened by andypa 4
  • Dynamic data

    Dynamic data

    Hi,

    I am wondering if I have a page that shows all the articles, how will the package know when to clear the cache? Do I have to clear the cache when there is a new article added to the DB?

    Thanks,

    opened by asivaneswaran 4
  • Page not loading from cached file

    Page not loading from cached file

    I am using this plugin, page cache is properly created in page cache folder but its not loading from it,

    my htaccess as below (puted in htaccess in root not in public)

    RewriteCond %{REQUEST_URI} ^/?$ RewriteCond %{DOCUMENT_ROOT}/public/page-cache/pc__index__pc.html -f RewriteRule .? public/page-cache/pc__index__pc.html [L] RewriteCond %{DOCUMENT_ROOT}public/page-cache%{REQUEST_URI}.html -f RewriteRule . public/page-cache%{REQUEST_URI}.html [L]

    Support 
    opened by jayeshm66 4
  • How to handle urls that sometimes contain a querystring

    How to handle urls that sometimes contain a querystring

    Its unclear to me how to handle urls that may sometimes contain a query string.

    For example, if you have a /blog url, and then pagination (/blog?page=2, /blog?page=3), etc.

    Unless I'm missing something, this package cannot handle query string's at all - it looks like only the actual uri is cached, and not the query string. Hence the example on the front page of the package demonstrating how to exclude routes that contain a query string.

    However, even if you implement that method, then the main /blog page will still get cached, which means that nginx will automatically serve up that same page for anything with a query string.

    I think there are 2 options here:

    • Don't implement caching at all for the /blog route
    • Somehow include query strings in the page-cache files (is this even possible)?
    opened by JonoB 3
  • Proposal: Adding the possibility of use in projects with different domains.

    Proposal: Adding the possibility of use in projects with different domains.

    Hello, By changing one line, functionality can be added to use the plugin with different domains.

    In the file src/Cache.php on line 198:

    - $segments = explode('/', ltrim($request->getPathInfo(), '/')); + $segments = explode('/', ltrim($request->getHost() . $request->getPathInfo(), '/'));

    It has been tested on Laravel 7 and it works for me. Is it a good idea? Is there something I'm missing?

    enhancement 
    opened by mlg1 3
  • Caching page from file does not open

    Caching page from file does not open

    Good afternoon.

    Laravel 7 / Mamp PRO / Apache

    I did everything according to the instructions, cache files are created successfully. But upon repeated access, the page cache file is not opened, but simply a new file is recreated.

    Please tell me what can I do wrong?

    I assume that the case is in htaccess file. Here are its contents: ` Options -MultiViews -Indexes

    RewriteEngine On
    
    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    
    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]
    
    # Serve Cached Page If Available...
    RewriteCond %{REQUEST_URI} ^/?$
    RewriteCond %{DOCUMENT_ROOT}/page-cache/pc__index__pc.html -f
    RewriteRule .? page-cache/pc__index__pc.html [L]
    RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.html -f
    RewriteRule . page-cache%{REQUEST_URI}.html [L]
    
    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
    
    # редирект на без www
    RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
    RewriteRule .* http://%1/$0 [L,R=301]
    
    # редирект с index.php на корень
    RewriteCond %{THE_REQUEST} ^.*/index\.php 
    RewriteRule ^(.*)index.php$ /$1 [R=301,L] 
    

    `

    Support 
    opened by mmg071 3
  • Use .json file extension instead of .html for JSON responses

    Use .json file extension instead of .html for JSON responses

    Hi Joseph,

    I was wondering if you would accept a PR which adds the ability to store a response in a .json file instead of a .html, if the response itself is a JSON document. The reason behind it is that the content-type in the browser would automatically be correct.

    Let me know what you think about it.

    Cheers!

    opened by andypa 3
  • Remove cache for home page

    Remove cache for home page

    Hi, i just using page-cache on my site and it's working like a champ. But how to clear cache for home page only "/" ? have try some slug but it's not working.

    opened by idberisi 1
  • Add ability to set custom cache paths in middleware to support multiple domains

    Add ability to set custom cache paths in middleware to support multiple domains

    Closes #99.

    Until this is merged it can be using in composer using:

    "require": {
        "silber/page-cache": "dev-master"
    },
        "repositories": [
            {
                "type": "vcs",
                "url": "https://github.com/michaellindahl/page-cache"
            }
        ],
    
    
    opened by michaellindahl 0
  • Caching Livewire pages

    Caching Livewire pages

    Hi all

    I'm trying to get this working with a Livewire page. There's only one small Livewire component on the page- the rest is static.

    I figured that as long as my /livewire/message/* path wasn't being cached it should work, but I'm running into issues.

    Has anyone been able to successfully cache Livewire pages with this package?

    Thanks!

    opened by binaryfire 1
  • multidomain Cache

    multidomain Cache

    Is it Somehow possible to make a subdirectory for the cache? We serve multiple domains via one laravel Project.

    e.g. testsite1.de, testsite1.at, testsite1.com

    unfortunately the index file is always overwritten and/or serves the wrong website.

    opened by MazzMazz 3
  • How to setup Cache on Cpanel?

    How to setup Cache on Cpanel?

    Can you help me with setting up page cache in Cpanel? Cpanel serves content from public_html by default so I am using this code to redirect all the requests to the public folder. The public_html contains all laravel content including Public folder. I can't make the cache work. I added the code to both public and main folder htaccess.

    Current htacess code I am using to redirect all requests ` RewriteEngine On RewriteRule ^(.*)$ public/$1 [L]

    `
    opened by hmzisb 0
Releases(v1.0.8)
Owner
Joseph Silber
Jack of all trades, master of some.
Joseph Silber
Invalidate caches and achieve high hitrate with readable and maintainable annotations

Purgatory Purgatory is an extension which makes it possible for Symfony applications to handle enormous load using minimal infrastructure. Infrastruct

null 45 Nov 30, 2022
Store your Laravel application settings in an on-disk JSON file

Store your Laravel application settings in an on-disk JSON file. This package provides a simple SettingsRepository class that can be used to store you

Ryan Chandler 24 Nov 16, 2022
A simple package allowing for consistent API responses throughout your Laravel application

Laravel API Response Helpers A simple package allowing for consistent API responses throughout your Laravel application. Requirements PHP ^7.4 | ^8.0

F9 Web Ltd. 441 Jan 5, 2023
Builds nice, normalized and easy to consume REST JSON responses for Laravel powered APIs.

REST API Response Builder for Laravel Master branch: Development branch: Table of contents Introduction Why should I use it? Usage examples Features E

Marcin Orlowski 614 Dec 26, 2022
A lightweight package for handling API error responses.

Laravel API Errors This package provides an easy way to manage and handle error response for JSON API's. Installation You can install the package via

3 SIDED CUBE 2 Feb 9, 2022
Laravel Jsonable - Well-Formated Responses & Exceptions.

Laravel Jsonable Well-Formated Responses & Exceptions. Documentation You can find the detailed documentation here in Laravel Jsonable Documentation. C

Pharaonic 1 Aug 7, 2022
Laravel Responder - a package for building API responses, integrating Fractal into Laravel and Lumen

A Laravel Fractal package for building API responses, giving you the power of Fractal with Laravel's elegancy.

Alexander Tømmerås 776 Dec 25, 2022
This package aims to help you standardize all your API responses in a simple and structured way.

Laravel API Response This package aims to help you standardize all your API responses in a simple and structured way. By default, the stucture of the

Kode Pandai 6 Dec 6, 2022
Renders consistent HTTP JSON responses for API-based projects

Laravel API Response is a package that helps to provide and render a consistent HTTP JSON responses to API calls as well as converting and formatting

Kennedy Osaze 43 Nov 20, 2022
This package provides a Logs page that allows you to view your Laravel log files in a simple UI

A simplistics log viewer for your Filament apps. This package provides a Logs page that allows you to view your Laravel log files in a simple UI. Inst

Ryan Chandler 9 Sep 17, 2022
Localization Helper - Package for convenient work with Laravel's localization features and fast language files generation

Localization Helper Package for convenient work with Laravel's localization features and fast language files generation. Installation Via Composer $ c

Galymzhan Begimov 0 Jul 13, 2019
A laravel package to generate class files from stub files.

Laravel Stub Generator A php laravel package to generate useable php files from given stub files . Installation Require the package using composer: co

Touhidur Rahman 31 Dec 29, 2022
A Laravel package that allows you to use multiple ".env" files in a precedent manner. Use ".env" files per domain (multi-tentant)!

Laravel Multi ENVs Use multiple .envs files and have a chain of precedence for the environment variables in these different .envs files. Use the .env

Allyson Silva 48 Dec 29, 2022
Laravel Quran is static Eloquent model for Quran.

Laravel Quran بِسْمِ ٱللّٰهِ الرَّحْمٰنِ الرَّحِيْمِ Laravel Quran is static Eloquent model for Quran. The Quran has never changed and never will, bec

Devtical 13 Aug 17, 2022
Laravel package that converts your application into a static HTML website

phpReel Static Laravel Package phpReel Static is a simple Laravel Package created and used by phpReel that converts your Laravel application to a stat

phpReel 16 Jul 7, 2022
The official Statamic 3 static site generator package

Statamic Static Site Generator Generate static sites with Statamic 3. Installation Install the package using Composer: composer require statamic/ssg

Statamic 187 Dec 25, 2022
This package provides a console command to convert dynamic JS/CSS to static JS/CSS assets.

Laravel Nova Search This package provides a console command to convert dynamic JS/CSS to static JS/CSS assets. Requirements laravel-mix v6.0+ php 7.3+

Akki Khare 3 Jul 19, 2022
HydePHP - Elegant and Powerful Static App Builder

HydePHP - Elegant and Powerful Static App Builder Make static websites, blogs, and documentation pages with the tools you already know and love. About

HydePHP 31 Dec 29, 2022
Allows Filament static assets (css, js) to be served directly from /public

Filament Static Asset Handling This package aims to solve improve the static asset handling of the amazing Laravel package Filament. By default Filame

Jamie Holly 8 Dec 6, 2022