Site performance and caching content

Processing and rendering content in a CMS is a relatively time consuming activity, particularly with complex pages that render external feeds or loop over other content nodes.

So as with regular websites it makes sense to use standard browser caching features to reduce the number of requests for content and supporting HTTP mechanisms for detecting changes to content.

Weceem supports both of these aims by implementing smart ETag handling as well as allowing you to tell the browser how long to keep the content for before checking for new versions using ETag. With ETags, the browser still makes a request to the server to check for changes, but if there has been no change, receives no new content.

This is done by calculating ETags for all URIs in your repository, based on the contents of other nodes on which those depend. For example even a simple home page is dependent on at least a Template node and likely at least a couple of widgets. This information is cached by Weceem, so checking for new content is very quick.

However this means that the ETag for your home page must change if the Template or widgets have been edited - otherwise users will continue to see your old home page styling for some time.

Weceem handles this by allowing you specify the URIs of content that a node is dependent on, a "maximum age" and also whether content contains user-specific information (which means that a different ETag is used per user).

Content Dependencies

When editing content, there is a "Content dependencies" field in the Advanced settings. This is where you enter a comma-delimited list of URIs on which the content node depends. By dependency we mean that this content's visual representation may change if any of these nodes are changed.

Wild cards of the form /** are supported, to represent any dependents.

There is however no need to specify dependency on the content Template, because this is handled automatically for you.

For example a Template used for your entire site may render widgets for header and footer. If you want all content that uses this template to become invalidated if the header or footer change, you would set the content dependencies to e.g:

widget/header, widget/footer

If you had a dependency on a lot of widgets, you could simplify this with the wildcard:


Another example is a News widget that uses wcm:eachChild to iterate over the news article nodes at URI "news-articles". Here you'd set the content dependencies of the widget to:


This way, any template that depends on this news widget, will also depen on the news articles, and hence everything invalidates as appropriate.

NOTE: some content types are smart and add some implicit dependencies. For example Blog automatically depends on its BlogEntry children. This is required because a Blog page normally lists its child nodes, and needs to update if new
entries are added.

Controlling how long a browser may keep a cached page

Aside from the dependencies, you can tell the browser how long to wait before checking for new content. For example if you know that usually you don't post more than one news article per day, and that even if you did you didn't mind someone not seeing the very latest, you can tell Weceem this.

Each content node has a setting labelled "Is updated" in Advanced. Here you can select how often the node is likely to be updated. If you never want it to be cached you can set this to "All the time". If you know that the content is unlikely to change you can set it to something like "Weekly" or "Never"

Doing this reduces the requests made to your server - saving you CPU time and bandwidth, and improving the response time of your site for users.

Note that if a user uses the "refresh" button in their browser, they will always get the newest content.

User-specific content

In some cases you may use Weceem's advanced scripting and widget features to present user-specific information. This typically uses the HTTP session to store user information, such as the contents of a shopping cart, or their user ID.

By ticking the "User specific content" option (available on Template nodes only in 1.0), you can instruct Weceem to allow the client to use cached content but still update if that user's rendering of the content will have changed.

When checked, this option forces Weceem to create a user-specific ETag for the content using that template. This is done by monitoring the HTTP session for changes. Any changes to the HTTP session result in a new ETag for pages using
that template.

If you have other data changes that should invalidate the user's view of the content, but don't directly change the session, you can force this simply by writing to the session.

For example if you have a Widget that renders a log in / log out button depending on whether the user has a cookie or not (perhaps for a separate app on the same domain) you simply make that widget set a variable in the session if the cookie value is no longer present:

<g:set var="hasCookie" value="${request.cookies.find { == 'userInfo' }?.value}"/>

<%-- only if the presence of cookie has changed to we change the session --%>
<g:if test="${session.userLoggedIn != hasCookie}">
   <g:set var="userLoggedIn" scope="session" value="${hasCookie}"/>

<%-- render the links --%>
<g:if test="${hasCookie}">
  <wcm:link path="user/logout">Log out</a>
  <wcm:link path="user/login">Log in</a>


eMail Page   Print
      Delicious   submit to reddit