You already have learned that ColdFusion allows you to cache query results. It also provides a page-caching feature, which enables you to cache the complet260 page that each of your templates generates. Similar to query caching, ColdFusion's page-caching feature is designed to improve your Web pages' overall performance.
The idea is simple. If you have certain ColdFusion templates that are time-consuming or get hit often, you can tell ColdFusion to cache them for a specified period of time. This can have a huge effect on overall application performance. The caching can take place on the browser machine, on the server machine, or on both.
If you want ColdFusion to cache a page, place the <cfcache> tag at the top of the template, before any other CFML o273 tags. The most important attribute for the <cfcache> tag is the action attribute, which tells ColdFusion whether you want the page cached on the client machine, on the ColdFusion server machine, or on both.
The <cfcache> tag can provide two types of caching: client-side page caching and server-side page caching. Both are of great benefit. Let's look first at client-side page caching, which is of particular relevance when you're putting together personalized pages that might take some time to display. Then we will look at server-side page caching, which is most useful for putting together non-personalized pages that get hit very often.
Finally, we will see how to use client-side and server-side page caching together, usually the best option.
All modern Web browsers provide some type of internal page-caching mechanism. As you use your Web browser to visit sites, it makes local copies of th260 for each page, along with local copies of any images or other media files the pages contain. If you go back to that same page later, the browser will show you the local copies of the files, rather than refetching them from the Web server. Your browser also provides settings you can use to control where the cached files are kept and how large the collection of all cached files can get. If it weren't for your browser's cache, most casual Web browsing would be much slower than it is.
Normally, the browser just relies on these settings to determine whether to display a page from its local cache or to recontact the Web server. If you haven't adjusted any of these settings, your own browser is probably set to use the cached copy of a page until you close the browser. When you reopen the browser and visit that same page, the browser recontacts the Web server and fetches the page afresh.
To view the current cache settings for a Firefox browser, choose Tools > Options > Privacy > Cache. For Internet Explorer, choose Internet Options from the Tools menu, then click the Settings button under Temporary Internet Files.
The <cfcache> tag gives you programmatic control over when the browser should use its local, cached copy to display a page to the user. You use the timeSpan attribute to tell ColdFusion how old the browser's cached version of the page can be before ColdFusion should refetch it from the server. If the browser fetched its local copy of the page after the date you specify, it uses the local copy to show the page to the user. If not, it visits the template normally. Table 25.2 summarizes the attributes relevant for this use of the <cfcache>.
ATTRIBUTE | PURPOSE |
---|---|
action | Must be set to ClientCache to use client-side caching only. You can also set this attribute to several other values to enable server-side caching, which the next section describes. You can also set it to CACHE, which uses both client-side and server-side mechanisms (see "ColdFusion-Optimized Caching," later in this chapter). |
timeSpan | The period of time you want the page to remain cached by the user's browser. You can specify this period using any combination of days, hours, minutes, or seconds, by providing a value returned by the createTimeSpan() function.If a simple number is passed, it is the number of days the cached is used. For example, 0.5 would result in a cache of one half day. A value of 1 would result in a cache lasting one day. |
For instance, if you wanted the browser to use its local copy of a page for six hours at a time, you would include the following at the top of your ColdFusion template:
<!--- Let browser use a cached version of ---> <!--- this page, from up to six hours ago ---> <cfcache action="ClientCache" timeSpan="0.25">
If you wanted to cache all pages in an application, you could simply place the <cfcache> tag in your Application.cfc file. That would cause all page requests to be cached (except for form submissions, which never are).
The first time a user visits the page, ColdFusion processes the template normally and sends the generated page back to the browser. The browser then stores the page in its local cache. The next time the user visits the same page, the browser quickly contacts the server, providing the server with the exact date and time that the page was visited the first time (that is, the date and time the local copy was saved). If the browser tells the server that its local copy is not older than the date specified in timeSpan, the server then tells the browser to show the local copy to the user and immediately stop processing the rest of the template. Otherwise, ColdFusion tells the browser that the local copy is now out of date; processes the rest of your code normally; and returns the newly generated version to the browser, where it can be cached locally for the next six hours (or whatever interval you specify).
By using <cfcache>, you can keep the amount of interaction between the browser and server to a minimum. Yes, the browser will contact the Web server, and ColdFusion will begin executing your template code. But as soon as ColdFusion encounters the <cfcache> tagwhich should be at the top of your CFML codeColdFusion will often be able to tell the browser to just use its local copy of the page. This is a fast operation because only the initial handshake between browser and server is necessary to determine whether the local copy can be used.
This improves performance in three important ways:
The browser can display the template more quickly. This is because it can just use the local copy instead of waiting for your template code to generate the template and refetch it over the Net. The longer the page and the more time-consuming your CFML code is, the greater the benefit.
It cuts the amount of work ColdFusion needs to do. As long as the browser's local copy is still valid, ColdFusion can stop processing your template as soon as it encounters the <cfcache> tag. This frees ColdFusion to complete its next task more quickly, which benefits all your users. The more often the same users revisit your pages, the greater the benefit.
By reducing the number of times complete pages must be sent back to browsers, traffic on your local network is kept to a minimum. This makes better use of your network bandwidth. Again, the more often the same users revisit your pages, the greater the benefit.
With Netscape browsers, you can override the client-side cache for a particular page request by doing what Netscape calls a super reload (which means holding down the Shift key while clicking the browser's Reload button). This can be useful for testing your pages. You can do the same with most versions of Internet Explorer by holding down the Ctrl key (or equivalent) while clicking the browser's Refresh button.
You can also use the <cfcache> tag to enable ColdFusion's server-side page caching mechanism. Like client-side caching, this method takes advantage of a previously generated version of your template code. However, server-side caching doesn't use the cached copy of the page that might be on the browser machine. Instead, it looks for a cached copy of the page that ColdFusion stores on the server's drive.
To enable server-side caching for one of your templates, place a <cfcache> tag at the top of the template before your other CFML an259 tags. As you can see in Table 25.3, a number of attributes are relevant for using <cfcache> to do server-side caching. They are all optional, however, and most of them are relevant only if your template is secured via SSL encryption or a user name and password. Most of the time, you can just specify action="ServerCache" and whatever timeSpan you desire.
ATTRIBUTE | PURPOSE |
---|---|
action | Set this attribute to ServerCache to enable server-side caching for your template. You can also set it to ClientCache to enable client-side caching only, as discussed above. Finally, you can set it to Cache (the default), which uses both client-side and server-side mechanisms (see the section "ColdFusion-Optimized Caching," later in this chapter). |
timeSpan | As with client-side caching, this is the period of time that you would like the user's browser to cache the page. You can specify this period using any combination of days, hours, minutes, or seconds by providing a value returned by the createTimeSpan() function. If a simple number is passed, it is the number of days the cached is used. For example, 0.5 would result in a cache of one half day. A value of 1 would result in a cache lasting one day. |
directory | Optional. The directory in which you want ColdFusion to store cached versions of the page. If this is omitted, ColdFusion stores the cached versions in a cache directory within the ColdFusion directory (or wherever you installed ColdFusion). |
username | Optional. If the template you want to cache normally requires the user to enter a user name and password, you must provide the appropriate user name here. Depending on the Web server software you are using, remember that the user name might be case sensitive. |
password | Optional. If the template you want to cache normally requires the user to enter a user name and password, you must provide the appropriate password here. Again, depending on your Web server, the password might be case sensitive. |
protocol | Optional. Specify either http:// or https://, depending on whether the template you want to cache is being served using SSL encryption. Normally, you can omit this attribute. This value defaults to the protocol of the current request. |
port | Optional. If the Web server is serving documents at a nonstandard HTTP port, specify that port number here. Otherwise, you can omit this attribute, in which case it defaults to the port of the current request. |
For instance, you could place the following snippet at the top of any of your ColdFusion templates. It tells ColdFusion that your template code only needs to execute once every 30 minutes at most:
<!--- Let browser use a cached version of ---> <!--- this page, from up to six hours ago ---> <cfcache action="ServerCache" timeSpan="#createTimeSpan(0, 0, 30, 0)#">
The first time the template is accessed, ColdFusion processes your code as it would normally do. But before it sends the generated page back to the browser, it also saves the page as a separate, static file on the server's drive. The next time the page is accessed, ColdFusion simply sends back the static version of the file without executing any code that appears after the <cfcache> tag. ColdFusion will continue to send this static version back to all visitors until 30 minutes have passed. After the 30 minutes have elapsed, the next page request reexecutes your template normally.
For most situations, that's all you have to do. Your visitors will immediately begin to see improved performance. The more often your pages are hit and the longer your template code takes to execute, the larger the benefit.
Listing 25.2 is a simple example that demonstrates this effect. The template uses the timeFormat() function to output the current time. At the top of the template, the <cfcache> tag allows the page to be cached for 30 seconds at a time. Try visiting this page repeatedly in your browser.
<!--- Filename: ServerSideCache.cfm Author: Nate Weiss (NMW) Purpose: Demonstrates use of server-side caching ---> <!--- Cache this template for 30 seconds at a time ---> <cfcache action="ServerCache" timespan="#createTimeSpan(0, 0, 0, 30)#"> &l275> <head><title>Caching Demonstration</title></head> <body> <!--- Display the current time ---> <p>This page was generated at: <cfoutput>#timeFormat(now(), "h:mm:ss tt")#</cfoutput> </body> <l>
The first time you visit this template, it displays the current time. For the next 30 seconds, subsequent page accesses will continue to show that same time, which proves that your template code is not re-executing. Regardless of whether you access the page using another browser or from another machine, click the browser's Reload or Refresh button, or close and reopen the browser, you will continue to see the original time message until the 30 seconds have elapsed. Then the next page request will once again reflect the current time, which will be used for the next 30 seconds.
Remember, if you are using <cfcache> for server-side caching (that is, with an action of Cache or ServerCache), the page won't be regenerated for each user. In particular, you should make sure that the page doesn't depend on any variables kept in the CLIENT, COOKIE, or SESSION scopes because the generated page will be shared with other users, without checking that their CLIENT, COOKIE, or SESSION variables are the same. So in general, you shouldn't cache personalized pages using server-side caching. For personalized pages, enable client-side caching with action="ClientCache" instead.
So far, you have learned about client-side page caching (that is, using <cfcache> with action= "ClientCache") and server-side page caching (action="ServerCache").
As noted earlier in Tables 25.2 and 25.3, you can use both types of caching together by specifying action="Cache" or by omitting the action attribute altogether. For each page request, ColdFusion will first determine whether the browser has an appropriate version of the page in its local cache. If not, ColdFusion determines whether it has an appropriate version of the page in its own server-side cache. Only if there isn't an appropriate version in either cache will your template code re-execute.
The result is greatly enhanced performance in most situations.
In previous versions of ColdFusion, the default value for action resulted in server-side caching only. In ColdFusion, the default is for both types of caching to be enabled. So if you move an application to ColdFusion and the code doesn't provide an action attribute, the server-side cache and client-side caches will both be enabled. This shouldn't be a problem, since nearly any situation that would benefit from server-side caching will also benefit from client-side caching as well.
ColdFusion maintains a separate cached version of your page for each combination of URL parameters with which it gets accessed. Each version expires on its own schedule, based on the timeSpan parameter you provide. In other words, you don't need to do anything special to employ server-side caching with pages that use URL parameters to pass ID numbers or any other information.
ColdFusion doesn't cache the result of a form submission, regardless of whether the target page contains a <cfcache> tag, so <cfcache> is disabled whenever the CGI.request_method variable is set to POST.
Remember, if you are using <cfcache> for server-side caching, the page won't be regenerated for each user, so server-side caching shouldn't be used for pages that are personalized in any way. The only type of caching that is safe for personalized pages is client-side caching (action="ClientCache"). See the important caution in the previous section.
By default, ColdFusion stores the cached versions of your templates in a folder called cache, located within the ColdFusion installation directory. If after visiting Listing 25.2, you look in the directory where you saved the listing, you will notice that ColdFusion has placed a file there, with a .tmp extension. If you open this .tmp file in a text editor, you will see that it contains the final, evaluated code that the ColdFusion template generated. A new .tmp file will appear in the folder whenever you visit a different template that uses server-side caching. In addition, a different .tmp file will appear for each set of URL parameters supplied to the templates when they are visited.
If you want to store the .tmp files in some other location, you can use the directory attribute to tell ColdFusion where to store them. You must provide a fully qualified file path to a folder on your server's drive (or on a local network, although this is not recommended).
For instance, the following would tell ColdFusion to store its cache files in a folder called cachefiles:
<!--- Cache this template for 30 seconds at a time ---> <cfcache action="Cache" timeSpan="#createTimeSpan(0,0,0,30)#" directory="c:\cachefiles">
You would, of course, need to create the cachefiles directory on the server machine before this would work.
The directory value shouldn't be within the Web server's document root. You don't want people to be able to request the .tmp files directly via their browsers.
Earlier in this chapter, you learned about query caching and how to make a cached query refresh when the data in the underlying database tables change. You have the same option for server-side page caching, via the flush action provided by the <cfcache> tag. You can also delete ColdFusion's cache files manually.
To flush a page from the cache before it would time out on its own, simply use the <cfcache> tag with action="flush". Table 25.4 shows the attributes relevant for flushing the server-side page cache.
ATTRIBUTE | PURPOSE |
---|---|
action | Must be set to Flush to flush pages from the server-side cache. |
directory | Optional. The directory that contains the cached versions of your pages. In other words, provide the same value here that you provide to the directory attribute in your other <cfcache> tags (the ones that enable caching). |
expireURL | Optional. A URL reference that represents which cache files to delete. If you don't provide this attribute, ColdFusion will flush the cache for all files in the specified directory. You can use an asterisk (*) in this attribute as a simple wildcard. |
If one of your templates makes some type of change that your application should reflect immediately, even in pages that would otherwise still be cached, you could use the following line to delete all cached pages in the current directory. You would place this code in the change template, right after the <cfquery> or whatever else is making the actual changes:
<!--- Flush the server-side page cache ---> <cfcache action="Flush">
If you don't need to expire all cached pages from the directory, you can provide an expireURL attribute. For instance, suppose you are using server-side caching to cache a template called ShowMovie.cfm, and that movie accepts a URL parameter called FilmID. After some kind of update to the Films table, you might want to flush the ShowMovie.cfm template from the cache, but only for the appropriate FilmID. To do so, you might use code like the following:
<!--- Flush the server-side page cache ---> <cfcache action="Flush" expireURL="ShowMovie.cfm?FilmID=#FORM.FilmID#">
Or to flush the cache for all versions of the ShowMovie.cfm template (regardless of URL parameters), leaving all other cached pages in the directory alone, you would use something like this:
<!--- Flush the server-side page cache ---> <cfcache action="Flush" expireURL="ShowMovie.cfm?*"> Controlling White Space
One of the side effects of CFML's tag-based nature is the fact that white-space characters (such as tabs, spaces, and return characters) that you use to indent your CFML code are usually passed on to the browser as part of the final generated page. In certain cases, this white space can considerably inflate the size of the generate259 content, and this in turn can hurt performance. ColdFusion provides several options for dealing with these extraneous white-space characters.
ColdFusion's ability to automatically control white space is better than ever in ColdFusion. You will find that in most cases, you can just enable the automatic Whitespace Management feature (discussed in a moment) and never think about white space issues again. Nonetheless, it is worthwhile to discuss the other options available to you, just in case.
In a ColdFusion template, you use CFML an259 tags together. The processing instructions for the server are intermingled with what you actually want to generate. That is, there is no formal separation between the code and the content parts of your template. Most other Web scripting environments separate code from content, generally forcing you to put th260 code you want to generate into some type of Write() function or special block delimited by characters such as <% and %> (depending on the language).
The fact that you get to use CFML tags right in the body of your document is a big part of what makes ColdFusion development so powerful, but it has a disadvantage. Often ColdFusion can't easily determine which white space characters in a template just indent the code for clarity and which should actually be sent to the browser as part of the final, generated page. When Cold Fusion can't make the distinction, it errs on the side of caution and includes the white space in the final content.
The good news is that ColdFusion already does a lot to eliminate excess white space from your generated pages. ColdFusion includes an automatic white-space elimination feature, enabled by default. As long as you haven't disabled this feature, it's already pulling much white space out of your documents for you, before the generated page is sent to the browser.
On the Settings page of ColdFusion Administrator, you'll see an option called Enable Whitespace Management. When this is enabled, portions of your template that contain only CFML tags will have the white space removed from them before the page is returned to the browser. Basically, ColdFusion looks at the template, finds the areas that contain only CFML tags, removes any white space (extra spaces, tabs, indents, new lines, or hard returns) from those areas, and then processes the template.
It's easy to see this in action. To do so, follow these steps:
1. | Visit the NextNCached.cfm template (refer to Listing 25.1) via your Web browser. |
2. | Use the browser's View Source option to see the fina267 code that the template generated. Leave the source code's window open. |
3. | On the Settings page of ColdFusion Administrator, uncheck (or check) the Enable Whitespace Management option and submit the changes. |
4. | Visit the NextNCached.cfm template and view the source code again. |
If you compare the two versions of the page source, you will see that the second (or first) version has a lot more blank lines and other white space in it. In particular, it has a lot more space at the very top, consisting of all the white space that surrounds the comments and various <cfquery>, <cfparam>, and <cfset> tags at the top of Listing 25.1. The first version of the page source has eliminated that white space from the top of the document.
There are very few situations in which this automatic suppression of white space would be undesirable. In general, you should leave the Enable Whitespace Management option enabled in Cold Fusion Administrator.
You can turn off ColdFusion's automatic white-space suppression feature for specific parts of your document. Such situations are rare becaus260 usually ignores white space, so there is generally no need to preserve it.
However, in a few situations you wouldn't want ColdFusion to remove white space for you. For instance, a few rarely use259 tags like <pre> and <xmp> do consider white space significant. IfChapter 27, "Interacting with Email").
In such a situation, you can use the suppressWhitespace="No" attribute of the <cfcfprocessingDirective> tag to disable the automatic suppression of white space. Place the tag around the block of code that is sensitive to white-space characters, like so:
<cfprocessingDirective suppressWhitespace="No"> <pre> ...code that is sensitive to white space here... </pre> </cfprocessingDirective>
<cfprocessingDirective> tag in Appendix B, "ColdFusion Tag Reference."
Unfortunately, ColdFusion can't always correctly identify which parts of your code consist only of CFML tags and should therefore have white space automatically removed. This is most often the case with code loops created by <cfloop> and <cfoutput>.
If you find that a particular portion of code generates a lot of unexpected white space, you can add the <cfsilet> tag, which suppresses all output (even actual text an259 tags). The <cfsilent> tag takes no attributes. Simply wrap it around any code blocks that might generate extraneous white space when executed, such as <cfloop> or <cfoutput> loops that perform calculations but don't generate any output that the browser needs to receive.
The <cfsilent> tag doesn't just suppress white-space output. It suppresses all output, even output you would generally want to send to the browser (such a274 code and text).
For situations in which ColdFusion's automatic suppression isn't suppressing all the white space in your generated pages (for instance, the first <cfloop> snippet in the previous section), but where <cfsilent> is too drastic, you can use the <cfsetting> tag to suppress output in a more selective manner.
The <cfsetting> tag takes a few optional attributes, but the only one relevant to this discussion is the enableCFOutputOnly attribute. When this attribute is set to Yes, it suppresses all output (similar to how the <cfsilent> tag works), except for <cfoutput> blocks. Any HTML code or text that should be sent to the browser must be between <cfoutput> tags, even if the code doesn't include any ColdFusion variables or expressions. This is different from ColdFusion's normal behavior, where it assumes that it can send any non-CFML text or code to the browser.
Appendix B, "ColdFusion Tag Reference," for more information about the <cfsetting> tag.