This articleArticleThis article explains a client-side page caching technique-caching static "parts" of pages in JavaScript ".
If the entire page can be cached on the browser, a huge page loaded with HTML can also run very well. You can use the HTTP Response cache header to solve this problem, or manually inject them into yourCodeOr use the @ outputcache tag on the ASPX page to declare:
<% @ Outputcache location = "client" Duration = "86400" varybyparam = "*" varybyheader = "*" %>
However, these cache records on the browser can only be maintained for one day. If you have a page with both static and dynamic content, you cannot use this output cache format at the page level. Generally, the page, logo, navigation menu on the left, and footer of the site are static parts. For details, refer:
In fact, only Region 2 is absolutely dynamic. region 1 and Region 3 and footer and menu can be partially or even fully cached!
Sometimes many parts of the main area of the page do not change frequently. It takes a considerable amount of download time to merge all the data. In this way, when some valid parts never change, users also have to constantly download their page records to the local device. If you can cache these static parts in the browser, you will download a lot of bytes each time the page is loaded. If the size of the entire page is 50 kb, at least 20 KB of content is static, while other 30kb may be dynamic. If you can use the client cache of the page fragment (not the output cache of the server page of Asp.net), you can easily save the download time by 40%. In addition, you do not need to send requests to the server for these static content because they have been cached in the browser. Therefore, the server does not have to process such a huge page each time it loads.
Asp.net provides the page segment cache by using @ outputcache. Although this is indeed very beneficial, the problem is that the cache is based on the server. It is responsible for returning the output of the user control and returning it from the server cache. However, you cannot eliminate the cost of downloading these bytes. Because it only saves some CPU processing capabilities on the server, this does not have much benefit for users.
The only way to cache page parts is to allow the browser to download these parts separately and make these parts cache like images, CSS or JavaScript files. Therefore, we need to download the page fragments separately and cache them into the browser cache. The IFRAME framework is easy to implement in this way, but it makes the page very clumsy and does not support page CSS styles adapted to the parent framework. In the IFRAME framework, you need to download other JavaScript code and Ajax framework that you may want to use again. Since these files are obtained from the cache, although the download speed seems to be very fast, it will increase the pressure on the browser to download the entire framework and a large amount of JavaScript code again.
There is a better way: use JavaScript code to present the page content, so that JavaScript will get the content from the browser cache. The idea is as follows:
1. Divide the entire page into many parts.
2. Use JavaScript code to generate page content. Each part that can be cached is controlled by the JavaScript code and then presented to the html
3. the browser only caches the cacheable parts, so they are not downloaded again (until the user refreshes or clears the cache ). The non-cacheable parts on the page, although frequently changing but not cached by the browser, are considered as page layout, as shown in:
For a typical homepage layout, the main segment is dynamic, while the header and footer, left menu, and logo are static
Because only the body is dynamic, the rest of the page is completely cacheable. Therefore, the entire page displayed by default. aspx looks similar to the following code:
<% @ Page Language = "C #" autoeventwireup = "true" codefile = "default. aspx. CS "inherits =" _ default "%> <br/> <% @ outputcache nostore =" true "location =" NONE "%> </P> <p> <! Doctype HTML public "-// W3C // dtd xhtml 1.0 transitional // en" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> </P> <p> <HTML xmlns = "http://www.w3.org/1999/xhtml"> <br/> <pead runat = "server"> <br/> <title> </title> <br/> </pead> <br/> <body> <br/> <form ID = "form1" runat = "server"> <br/> <Table width = "100%" border = "1" style = "height: pixel PX "> <br/> <tr> <br/> <TD> some logo here </TD> <br/> <TD> <SCRIPT id =" script1 "src = "header. aspx "type =" text/JavaScript "> </SCRIPT> </TD> <br/> </tr> <br/> <TD> <SCRIPT id = "script2" src = "leftmenu. aspx "type =" text/JavaScript "> </SCRIPT> </TD> <br/> <TD bgcolor =" lightgrey "> <br/> <div> This is hte dynamic part which gets changed on every load. <br/> check out the time when it was generated: <% = datetime. now %> </div> <br/> </TD> <br/> </tr> <br/> <TD colspan = "2 "> <br/> <SCRIPT id =" script3 "src =" footer. aspx "type =" text/JavaScript "> </SCRIPT> <br/> </TD> <br/> </tr> <br/> </table> <br /> </form> <br/> </body> <br/> </ptml> <br/>
Caching all parts of the page on the browser can eliminate the occurrence of static download blocks. For example, headers, left menus, and footers are unchanged, so they are cached for repeated access, however, each time a user accesses the subject, the user needs to obtain new content from the server.
Cached parts will last for more than 30 minutes, because the browser will not download them from the server at all, and this also saves the transmission cost of big data. Only the entity is downloaded from the server.
During the first visit, the page will be downloaded one by one, as you can see:
However, during the second visit, only the default. aspx page is downloaded and other parts are loaded from the cache immediately. The following figure shows the instances that load different cached parts of the page.
During the second access, the cached content is immediately obtained from the browser cache. Therefore, the entire downloaded byte is only performed on the default. aspx page, rather than a small part of the page. Therefore, the download time is greatly reduced and the re-access time is also very fast.
Compared with the download time of 1 s for each block on the first access page, the download time for partial areas of the second access page is between 5 and 7 ms. This shows how fast it is to access some cached areas of the page again.
Let's take a look at a file named header. aspx whose content is obtained from the cache.
Cache the header. ASPX page. Note that compared with a standard ASPX page, only the contenttype attribute is changed.
<% @ page Language = "C #" autoeventwireup = "true" codefile = "header. aspx. CS "inherits =" Header "contenttype =" text/html/JavaScript "%> <br/> <% @ outputcache location =" client "Duration =" 86400 "varybyparam = "* "%> </P> <p> <! Doctype HTML public "-// W3C // dtd xhtml 1.0 transitional // en" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> </P> <p> <HTML xmlns = "http://www.w3.org/1999/xhtml"> <br/> <pead runat = "server"> <br/> <title> </title> <br/> </pead> <br/> <body> <br/> <form ID = "form1" runat = "server"> <br/> <div> <br/> <p> This is the big fat header. lots of HTML </p> <br/> generater on server at: <% = datetime. now %> <br/> </div> <br/> </form> <br/> </body> <br/> </ptml> <br/>
Content type is set to text/html/JavaScript values, which requires manual Implementation of the page.
An error occurs when you place An ASPX page in a script tag. Because the expected output of <SCRIPT id = "script1" src = "header. aspx" type = "type/JavaScript"> is JavaScript rather than HTML content. If HTML output is provided, the browser ignores it completely. Therefore, to ensure that the <SCRIPT> tag works properly, the header. ASPX page must return JavaScript code instead of HTML content. Secondly, the document. writeln method is used to render the HTML output of the header. ASPX page in JavaScript.
An HTTP module intercepts all call requests to the. ASPX page. When a page is sent to the browser, the system checks whether the content type is text, HTML, or JavaScript. If yes, convert the page output to a javascript-like representation.
Create a response filter file named html2jspagefilter. CS to overwrite the write method of the response stream and convert the HTML of the page to JavaScript. Therefore, Asp.net generates HTML for you and converts it to JavaScript to present the source HTML on the browser.
Filter attribute of httpresponse
Here we will use the filter attribute of httpresponse, which is very useful but rarely used. Msdn interprets it as -- gets or sets a encapsulated filter object to modify the HTTP entity content before it is transmitted to the client. In other words, you can set your own filter for each page output. Httpresponse sends all content to the filter
Use http Module
You may be wondering whether an HTTP handler can be used to handle this problem. For example, you need to use the default page handler of Asp.net to intercept all call requests that send files with the *. aspx extension. However, you cannot register a file with the same extension as another handler. In this solution, you need to use httpmodule, which can intercept any requests from the Asp.net pipeline. To implement this function, you need:
1. Return the output of the entire page in HTML Format
2. filter the content contained in the <form> label. Asp.net always generates a <form> label, and the content on the page is only available when the label is inside.
The following code returns the generated HTML content from the ASPX page and parses the content from the <form> tag.
Public override void write (byte [] buffer, int offset, int count) <br/>{< br/> string strbuffer = system. text. utf8encoding. utf8.getstring (buffer, offset, count ); <br/> // tags <br/> // wait for the colsing </ptml> tag <br/> // -------------------------------- <br/> RegEx EOF = new RegEx (" </ptml> ", regexoptions. ignorecase); </P> <p> If (! EOF. ismatch (strbuffer) <br/>{< br/> responsehtml. append (strbuffer); <br/>}< br/> else <br/>{< br/> responsehtml. append (strbuffer); <br/> string finalhtml = responsehtml. tostring (); </P> <p> int formtagstart = finalhtml. indexof ("<form"); <br/> int formtagstartend = finalhtml. indexof ('>', formtagstart); <br/> int formtagend = finalhtml. lastindexof ("</form>"); </P> <p> string pagecontentinsideformtag = finalhtml. substring (formtagstartend + 1, formtagend-formtagstartend-1 );
3. Remove the viewstate of the hidden field. Otherwise, it will conflict with the viewstate on the default. aspx page (the default page has its own viewstate ). Therefore, the <input> tag containing viewstate cannot be sent to the browser again. This means that you cannot use a control with viewstate, although it is a shortcut to achieve this method. Generally, the cache stores static content. Therefore, viewstate is not required here.
The following code removes the viewstate of the <input> field to avoid conflict with the viewstate of the default. aspx page:
RegEx Re = new RegEx ("(<input .*? _ Viewstate .*? />) ", Regexoptions. ignorecase); </P> <p> pagecontentinsideformtag = Re. Replace (pagecontentinsideformtag, String. Empty );
4. Convert the entire HTML output to the javascript string format. This string contains an unformatted HTML, which can be used as innerhtml or used in the document. Write ('') statement.
The following code converts the HTML output to a javascript string and removes new lines, spaces, and omitted characters. You can set this string to the innerhtml value of an element or pass it to the document method:
String javascript2html = pagecontentinsideformtag. replace ("\ r", "") <br/>. replace ("\ n", "") <br/>. replace ("", "") <br/>. replace ("", "") <br/>. replace ("", "") <br/>. replace ("\", "\") <br/>. replace ("'","\\'");
5. Use the document. Write method, which can output JavaScript strings to the browser. HTML is directly added to the page content
Generate a document. Write statement to output HTML to the browser:
String pageoutput = "document. write ('"+ javascript2html +"'); "; <br/> byte [] DATA = system. text. utf8encoding. utf8.getbytes (pageoutput); </P> <p> responsestream. write (data, 0, Data. length );
This is a perfect scam. Use a response filter to return the output of the. aspx file and convert it to JavaScript. Use the document. Write method to render HTML in the browser's Dom and obtain the JavaScript code cache. For convenience, an httpmodule object is used to hook the Asp.net pipeline and wait for the. aspx file to send text/html/JavaScript content. Then hook the response filter to the Asp.net request pipeline.
Register httpmodule
The httpmodule object is very simple. It will hook up the releaserequeststate event in the context. This event will be activated when the page output is ready to be sent to the browser. In the handle of this event, call the response filter to convert HTML to the Javascript format.
The following is the implementation code:
Public void Init (httpapplication context) <br/>{< br/> context. releaserequeststate + = new eventhandler (installresponsefilter); <br/>}</P> <p> private void installresponsefilter (Object sender, eventargs E) <br/> {<br/> httpresponse response = httpcontext. current. response; </P> <p> If (response. contenttype = "text/html/JavaScript") <br/>{< br/> response. contenttype = "text/JavaScript"; <br/> response. filter = new html2jspagefilter (response. filter); <br/>}< br/>}
Finally, add an entry node
<Httpmodules> <br/> <Add name = "html2jsmodule" type = "html2jsmodule"/> <br/> </pttpmodules>
You can use this method in your. aspx file to fully Save the download time on the client. Although the download time is slightly increased during the first visit-the average round-trip time of each script tag on the network is about 200 ms, it is easier to access the script again. Pay attention to these different performance problems: log on to www.pageflakes.com and load the whole site. Then, close the browser, open it, and enter the URL address again. We can see how fast the second access is. That's right. They use this technique! You will see that only 10-12 kb of data is sent for the second visit, compared with about KB data sent for the first visit. This is because all the page fragments are cached in the browser. As long as the cache has not expired, subsequent users do not need much download time to visit the site.
Source codeDownload