GithubHelp home page GithubHelp logo

rarst / fragment-cache Goto Github PK

View Code? Open in Web Editor NEW
140.0 15.0 10.0 40 KB

WordPress plugin for partial and async caching.

License: Other

PHP 100.00%
wordpress-plugin cache performance wordpress

fragment-cache's Introduction

Fragment Cache

Scrutinizer Code Quality

Fragment Cache is a WordPress plugin for partial and async caching of heavy front-end elements. It currently supports caching navigation menus, widgets, and galleries.

Caching is built on top of transients API (with enhancements provided by TLC Transients library), provides soft expiration and transparent object cache support.

Installation

Download plugin archive from releases section.

Or install in plugin directory via Composer:

composer create-project rarst/fragment-cache --no-dev

Frequently Asked Questions

Why fragments don't recognize logged in users / current page?

Fragment Cache implements soft expiration - when fragments expire, they are regenerated asynchronously and do not take time in front end page load. The side effect is that it is impossible to preserve context precisely and in generic way.

Fragments that must be aware of users or other context information should be excluded from caching or handled by custom implementation, that properly handles that specific context.

How to disable caching?

Disable handler

Caching for the fragment type can be disabled by manipulating main plugin object:

global $fragment_cache;

// completely remove handler, only use before init
unset( $fragment_cache['widget'] );

// or disable handler, use after init
$fragment_cache['widget']->disable();

Skip individual fragments

Caching for individual fragments can be disabled by using fc_skip_cache hook.

add_filter( 'fc_skip_cache', function ( $skip, $type, $name, $args, $salt ) {

	// Widget by class.
	if ( 'widget' === $type && is_a( $args['callback'][0], 'WP_Widget_Meta' ) ) {
		return true;
	}

	// Menu by theme location.
	if ( 'menu' === $type && isset( $args['theme_location'] ) && 'header' === $args['theme_location'] ) {
		return true;
	}

	// Menu by name.
	if ( 'menu' === $type && isset( $args['menu'] ) ) {

		if ( 'Menu with login' === $args['menu'] ) {
			return true;
		}

		if ( is_a( $args['menu'], 'WP_Term' ) && 'Menu with login' === $args['menu']->name ) {
			return true;
		}
	}

	// Gallery by ID of post.
	if ( 'gallery' === $type && 123 === $args['post_id'] ) {
		return true;
	}

	return $skip;
}, 10, 5 );

License Info

Fragment Cache own code is licensed under GPLv2+ and it makes use of code from:

  • Composer (MIT)
  • Pimple (MIT)
  • TLC Transients (GPLv2+)

fragment-cache's People

Contributors

rarst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fragment-cache's Issues

The transient name never includes the menu name

I am using Fragment Cache with Polylang a multilingual plugin. The problem that I realized is that Fragment Cache loads the same menu regardless of language for the same menu location.

The reason is that this line of code does not work or better said $args['menu'] always returns an empty string.
$name = is_object( $args['menu'] ) ? $args['menu']->slug : $args['menu'];

The reason is that if menu is not defined as an argument in the theme template it will be an empty string. The menu argument is only defined after pre_wp_nav_menu

https://developer.wordpress.org/reference/functions/wp_nav_menu/

Use `pre_wp_nav_menu` for the menu

Problem: I am currently adding the language switcher in the menu using wp_nav_menu_items. When I activate this plugin logically the URL stops changing.

I was looking for a way I could hook in after the cache was fetched but I could not find a way.

WordPress 3.9 introduced a new filter pre_wp_nav_menu that can be used to short-circuit the menu process. https://generatewp.com/how-to-use-transients-to-speed-up-wordpress-menus/

If you used the new filter then I could hook into it after the cache was fetched and add the language switcher.

function wpzoo_language_switcher( $object, $args ) {
    if ( ! is_null( $object ) ) {
        $object .= lanaguage_switcher();
    }
}
add_filter( 'pre_wp_nav_menu', 'wpzoo_language_switcher',10, 2 );

Clashes with Jetpack galleries

I just noticed that enabling fragment cache will render the Jetpack galleries (tiled and carrousel) useless. The Javascript throws an error resulting in not displaying the images or being able to close the modal.

Any idea why this would happen?

Consider style and script tracking

It's not too far fetched to try and track which scripts and styles callback is queueing to reproduce when serving cached copy.

I am not confident it makes sense at this point, but worth looking into.

Update conflict with wordpress.org plugin

Hey,

Thanks for a great plugin!

When you have this plugins installed(I installed it with composer) you get an update notification for this plugin. But the plugin WordPress wants to update to is this plugin: https://wordpress.org/plugins/fragmentcache/ (version 0.6.0).

I guess this plugin is matched by plugin name. Could you please change the plugin name to avoid this conflict? Add a prefix or something.

Thanks.

Review handling of widgets in Customizer

The last patch/approach with intercepting ajax request is a mess really.

@westonruter shared something to look into while back, which I need to get to finally:

the wp_ajax_update-widget action in the customizer is only used to invoke the WP_Widget::update() method to calculate the new widget instance state to then return back to the client. This is for back-compat for widgets which have historically relied heavily on PHP for their architecture. These update-widget Ajax requests are not supposed to be writing anything to the DB. So if you want to listen for when a widget is saved in the customizer, I think you should instead be looking at the customize_save_after action, and in there iterate over $wp_customize->settings() to identify which widgets were saved as part of the changeset. For example:

add_action( 'customize_save_after', function( $wp_customize ) {
  foreach ( $wp_customize->settings() as $setting ) {
	    if ( 'widget' === $setting->type && null !== $setting->post_value() ) {
  		// @todo Clear fragment cache for the widget.
  	}
  }
});

Adding 'fragment_cache_init'?

I was thinking about extend fragment cache with a couple of custom, site-specific, handlers. There is no documentation for this task but looking at code is pretty clear that to add additional handlers external code should rely on global $fragment_cache variable.

Leaving aside discussion about goodness of global variables, what I see is that there is no way to call $fragment_cache->add_fragment_handler on global $fragment_cache object before $fragment_cache->run(); is called.

What I propose is to add an hook, maybe 'fragment_cache_init' after global $fragment_cache object is created and default handlers have been added.

I forked and branched the repo to show with code what I mean: see https://github.com/Giuseppe-Mazzapica/fragment-cache/compare/fragment_cache_init-hook?expand=1

The benefits should be pretty clear: custom handlers can be added using that hook, something like:

add_action( 'fragment_cache_init', function( $fragment_cache ) {
  $fragment_cache->add_fragment_handler( 'gm-foo-bar', 'GM\\Foo\\Bar' );
} );

Side effect is that same hook can be used to disable specific handler initialization before it is enabled:

add_action( 'fragment_cache_init', function( $fragment_cache ) {
  unset( $fragment_cache['menu'] );
} );

Sure that hook can be used to do anything, ruin plugin integrity included, but actually global variable is not safer.

Skip cache examples for each object type

It would be very helpful to have fc_skip_cache examples for each object type, not just widgets.

It's difficult to figure out how best to disable caching in each scenario. Heck, it's hard just to figure out what the object is named, let alone how to target it.

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.