Skip to content
Grav 2.0 is officially stable. Read the announcement →
Plugins

Plugins and caching

Solved by pamtbaau View solution

Started by Aaron Dalton 8 years ago · 10 replies · 1959 views
8 years ago

I manage a Google Charts plugin. The problem is that if caching is on, the graphs only render on the first page hit. The graphs never render in the cached versions. Is there something I can do on the plugin end of things to rectify this?

8 years ago Solution

@Perlkonig Your plugin is using grav-plugin-shortcode-core to process the shortcode embedded in the page.

Inside your GChartShortcode::process() function you call addInlineJS to add Google's charting scripts.
ShortCode_Core calls your GChartShortcode::process() function inside Grav's onPageContentProcessed event. This event is only called once when cache is enabled.

On first run, the shortcode in the page is perfectly replaced by the placeholder for the chart. Also your inline javascript gets added to the Assets manager and added to the <head> of the page.

I'm just a Grav newbee and not that knowledgable on caching, so the following might be wrong.

While debugging the processing of a page, I noticed that Assets::js() is called on every page request. So assets are probably not cached and need to be added to the Asset manager at each request. Since your code is only called once on first page load, the required Google Charts script is no longer added. You can see in the generated page on subsequent loads that the scripts are missing.

When I change your script a little, the script is embedded into the page and also cached.

PHP
// $this->grav['assets']->addInlineJs($code);
...
return $output . "<script>$code</script>";

Now, the chart is shown on each and every page request. Cached or not...

👍 1
2 replies
last edited 07/06/18 by pamtbaau
8 years ago

I will take a look, thanks. I need to look more closely at why exactly things aren't rendering, because if you're online, even a cached version should redraw. Is there a way to manually add things to a cache? Back to the docs!

8 years ago

I guess I just assumed that doing it "right" by adding the code through the assets pipeline that the caching would be done automatically. I'll do some doc diving this weekend.

8 years ago

One strategy I implemented recently, to solve basically the same problem - assets would not render properly that were instantiated by a specific template (not global) - is to disable the cache for that specific template by having the plugin temporarily disable it.

8 years ago

@Perlkonig

Looking for an alternative to my previous solution where javascript is embedded in the cached page content.

Not sure which one is better, more efficient, or cleaner...

TLDR:

  • In GChartShortcode::process() save generated script into frontmatter of page.
  • Fetch javascript from page's frontmatter in google-charts.php during onTwigSiteVariables event and add to assets .
  • Charts will be drawn when cache is off and on...

Longread:
Did some tests to find the event when assest can be added. onTwigSiteVariables seems to be one of the latest. And it is after onPageContentProcessed in which your process() is running.

I made the following changes to your GChartShortcode::process():

  • Removed both addAssets()
  • Added the following right after you generated the javascript into $code:
    PHP
    $header->set('google-charts.test.script', $code);
    $this->grav['page']->header($header->items);
    $this->grav['page']->save();
    

And added the following function in google-charts.php:

PHP
public function onTwigSiteVariables()
{
    $header = $this->grav['page']->header();
    $header = new \Grav\Common\Page\Header((array) $header);
    $script = $header->get('google-charts.test.script');

    $this->grav['assets']->addJs('https://www.gstatic.com/charts/loader.js', ['group' => 'bottom']);
    $this->grav['assets']->addInlineJs($script, ['loading' => 'inline', 'group' => 'bottom']);
}

This way, the scripts are added in onTwigSiteVariables which is run when cache is both false and true.

8 years ago

Can't help being curious...

In GChartShortcode::process() you add assets in the following two ways:

PHP
1) $this->shortcode->addAssets('js', 'https://www.gstatic.com/charts/loader.js');
2) $this->grav['assets']->addInlineJs($code);

I was wondering, why does 1) get added while 2) does not when cache is enabled? Assets are not cached, so Shortcode Core must be doing something else. After some code digging...

Shortcode Core is using an approach that looks a bit like what I suggested in reply #9. However they do not store it inside the page's frontmatter (which I find kind of ugly), but in the page's metaContent, which also get's cached and can be retrieved later in onTwigSiteVariables.

Using this technique the approach could be as follows:
In your GChartShortcode::process():

  • Remove both addAssets()
  • Add the following right after you generated the javascript into $code:

    PHP
    $this->grav['page']->addContentMeta('gchart-script', $code);
    

    And add the following function in google-charts.php:

    PHP
    public function onTwigSiteVariables()
    {
    $code = $this->grav['page']->getContentMeta('gchart-script');
    
    $this->grav['assets']->addInlineJs($code);
    $this->grav['assets']->addJs('https://www.gstatic.com/charts/loader.js');
    }
    

    Pros & cons:

  • The advantage of this approach over injecting the javascript into the processed page content (reply #4), is that you gain flexibility as to how you would like to add the assets using priority, grouping, pipelining etc.
  • This disadvantage is it requires more coding...
  • The advantage of this approach over storing the script inside the page's frontmatter (reply #9) is that the end-user will not be confronted with a rather large chunk of code when editing the page.

I think I should close this chapter now...

Suggested topics

Topic Participants Replies Views Activity
Plugins · by Vladimir Novak, 2 weeks ago
3 292 2 weeks ago
Plugins · by Mathieu Lecouturier, 3 weeks ago
3 277 3 weeks ago
Plugins · by Slebeig, 2 months ago
1 403 2 months ago
Plugins · by Rene, 2 months ago
2 574 2 months ago
Plugins · by Xavier, 3 months ago
2 490 3 months ago