Speed up Page Loads with a Plugin

Dramatically reduce page-load times by using a plugin to place formatted data in the introtext (summary) field.


In the previous article, we looked at some plugins that execute when a resource is saved in the Manager. In this one, we'll see some plugin code that can dramatically speed up page loads by storing processed information in the resource's introtext field every time the resource is saved in the Manager.

For a variety of reasons, processing TVs every time a page is loaded can really slow things down. Especially if the TV tags are in a Tpl chunk used in an aggregating snippet like getResources. What if we could store the processed results of those tags in the resource's introtext field just once, when the resource is saved. Think of all the time that would be saved later on. This example can serve as an alternative to getResources, but it can also be used to dramatically speed up getResources by placing all the TV data in a single resource field.

The following example plugin should be connected to the OnDocFormSave event. To use it, paste the code into a plugin and, on the "System Events" tab, check the box next to OnDocFormSave. Then, save the plugin. In the code of a plugin attached to that event, the resource being saved is always available as the $resource variable.

More Fun with Dogs and Cats

In the previous article, we used an example that set TV values with the characteristics of dogs and cats. In this one, we'll assume that we have the same TVs, but we'll set the introtext (summary) field of each resource using a Tpl chunk containing placeholders for TV values that hold information about the animal.

As we did in the previous article, each cat or dog will have its own resource with TVs for the breed, weight, birth date, and description. All the dogs are stored under the "Dogs" folder, which has an ID of 12. All cats will be stored under the "Cats" folder, which has an ID of 22.

The method shown here can be used in a lot of different situations to essentially "pre-process" tags and save formatted output so the tags don't have to be parsed on every page load. If you don't want to use the introtext field, you could always store the formatted output in another field or in a dedicated TV.


Important: If you created the plugin from a previous article that writes the contents of the introtext field to the description field, be sure you remove or disable it. In this case we definitely *don't* want those fields to be the same.


In this plugin, we'll leave out the code from the previous article that limits execution to new resources. We want the plugin to execute whether it's a new resource or not. That way, when you change any of the relevant TV values, the introtext field will be updated when you save the resource.

Our Tpl chunk might look like this (let's call it "IntrotextTpl"):

<h3>[[+name]]</h3>

<p><b>Species: [[+species]]</b></p>

<ul>
    <li>Breed: [[+breed]]</li>
    <li>Weight: [[+weight]</li>
    <li>Birth date: [[+dob]]</li>
    <li>Description: [[+desc]]</li>
</ul>

Our plugin will use that Tpl chunk to process the tags and write the complete description to the introtext field of the resource.

The Code

Here's the code for our plugin:

$dogFolderId = 12;
$catFolderId = 22;

/* We'll use this array to hold the values
   to place in the chunk */
$fields = array(
'weight' => $resource->getTVValue('weight'),
);

/* Handle dogs */
if ($resource->get('parent') == $dogFolderId) {
$fields['species'] = 'Canine';
}

/* Handle cats */
if ($resource->get('parent') == $catFolderId) {
$fields['species'] = 'Feline';
}

/* Handle the other fields */
$fields['name'] = $resource->getTVValue('name');
$fields['breed'] = $resource->getTVValue('breed');
$fields['weight'] = $resource->getTVValue('weight');
$fields['desc'] = $resource->getTVValue('desc');
$fields['dob'] = $resource->getTVValue('birthdate');

$tpl = $modx->getChunk('IntrotextTpl', $fields);
$resource->set('introtext', $tpl);
$resource->save();
return '';

The MODX getChunk() method will retrieve a chunk and replace its placeholder tags with the values sent in the array in the second argument (in this case, $fields).

Now, you can display a fully-formatted description for any animal just by putting this tag on the page:

[[*introtext]]

This will give you a lot faster page loads than creating a regular Tpl chunk for the page since all the parsing is done once when the resource is saved, instead of doing it whenever the resource is viewed.

The example above is a little contrived, because in reality, you might have the animal's name in the pagetitle field and its description in the content field. In that case you might add this code in the plugin to set those placeholders:

$fields['name'] = $resource->get('pagetitle');
$fields['desc'] = $resource->get('content');

You might be wondering if the introtext (summary) field has enough room to store all the information you need to put there. The type of that field is TEXT. That means it has room for about 64,000 characters, so unless you're doing something completely insane, there should be plenty of room for your data. The description field, on the other hand, will take only 255 characters, so be careful if you use that field.

It has probably occurred to you that you could create a similar display with getResources, though the page-load times with our example would be *much* faster, and with getResources, it would be trickier to display cats and dogs in the same list unless you created a species TV, which would slow things down even more. If you wanted to display cats and dogs separately, it would be easy to use our example to generate a very fast display for each group using getResources, but without having getResources retrieve or process any TVs, which would speed things up immensely. You'd just put this tag in the AnimalDescriptionTpl chunk:

[[+introtext]]
The code on the page to display descriptions for all the animals might look something like this:
<h3>Dogs</h3>

[[!getResources? &parents=`12` &tpl=`AnimalDescriptionTpl`]]

<h3>Cats</h3>

[[!getResources? &parents=`22` &tpl=`AnimalDescriptionTpl`]] 

Now, getResources doesn't have to process any TVs at all. Notice that we don't have to use the Tpl we created above that formats the animal's description at all here. The fully-formatted description is already in the introtext field, which is why this method is so much faster.

A Final Note

One of the great things about this method is that you can actually see the results in the introtext (summary) field when you edit the resource. Don't be tempted to edit that field when editing a resource, though. Your changes will be overwritten as soon as you save the resource. If you want to change what's there, modify the Tpl Chunk used in your plugin. Remember that the changes won't show up for a particular resource until that specific resource is saved in the Manager. Clearing the Site Cache will *not* update the introtext field.

If you are using this technique and have other users, you might want to hide the introtext field from them with Form Customization so they won't be tempted to edit it.



Comments (1)

  1. Susan OttwellJul 30, 2014 at 02:59 AM

    This is really impressive! And, as you said, if the introtext field is already being used, this could be stored in a separate TV, so your getResources would only need to load one TV, with no processing at all. This would be especially useful if images are involved.


Please login to comment.

  (Login)