Yahoo! Developer Network Blog

« Previous | Main | Next »


July 18, 2007

High Performance Web Sites: Rule 8 – Make JavaScript and CSS External

Many of these performance rules deal with how external components are managed. However, before these considerations arise you should ask a more basic question: Should JavaScript and CSS be contained in external files, or inlined in the page itself?

Using external files in the real world generally produces faster pages because the JavaScript and CSS files are cached by the browser. JavaScript and CSS that are inlined in HTML documents get downloaded every time the HTML document is requested. This reduces the number of HTTP requests that are needed, but increases the size of the HTML document. On the other hand, if the JavaScript and CSS are in external files cached by the browser, the size of the HTML document is reduced without increasing the number of HTTP requests.

The key factor, then, is the frequency with which external JavaScript and CSS components are cached relative to the number of HTML documents requested. This factor, although difficult to quantify, can be gauged using various metrics. If users on your site have multiple page views per session and many of your pages re-use the same scripts and stylesheets, there is a greater potential benefit from cached external files.

Many web sites fall in the middle of these metrics. For these properties, the best solution generally is to deploy the JavaScript and CSS as external files. The only exception I’ve seen where inlining is preferable is with home pages, such as Yahoo!'s front page (http://www.yahoo.com) and My Yahoo! (http://my.yahoo.com). Home pages that have few (perhaps only one) page view per session may find that inlining JavaScript and CSS results in faster end-user response times.

For front pages that are typically the first of many page views, there are techniques that leverage the reduction of HTTP requests that inlining provides, as well as the caching benefits achieved through using external files. One such technique is to inline JavaScript and CSS in the front page, but dynamically download the external files after the page has finished loading. Subsequent pages would reference the external files that should already be in the browser's cache.

Steve Souders

[Steve Souders is Yahoo!'s Chief Performance Yahoo!. This is one in a series of Best Practices for Speeding Up Your Web Site. This article is based on Steve's book High Performance Web Sites, published by O'Reilly.]

Posted at July 18, 2007 8:05 PM | Permalink

Bookmark this on Delicious

Comments

Nice idea at the very end there. If the scripts are not too big (or if the JavaScript is generated with the client state) then inlining might actually be a better option, as I saw from load time analyzer extension for Firefox that it still takes some time to load even from the cache and reducing the number of external objects to load makes the page to load faster and if we gzip the size won't be too big. For example, in the classic Yahoo mail, there is lot of inline script.

Posted by: Kishore Senji at July 21, 2007 7:27 PM

How do you make them external?????
There is no example. Examples are always helpfull.


My guess is that instead of doing this:
<script type="text/javascript" src="/scripts/yahoo/yahoo-min.js"></script>

you would do this????
<script type="text/javascript" src="/scripts/yahoo/yahoo-min.js"></script>

Posted by: Rob ll at July 25, 2007 9:47 AM

mode external

print '-link media="all" type="text/css" rel= "stylesheet" href="/themes/vol/style.css" / style type="text/css"/style-';

internal:

print '-style type="text/css"-'. file_get_contents(" myfile.css")'.-/style-';

very good idea!!

print phpinfo();

Posted by: Nei Rauni Santos at July 27, 2007 7:43 PM

How does this align with Rule #1 -- reducing HTTP calls? Isn't each external file another HTTP call?

Posted by: Stephen Rider at October 31, 2007 10:37 AM

question,

suppose 10% of your CSS page contains dynamically generated css code using EL and tags with JSP. that means, 90% of the page can potentially be cached. but separating the cachable css and the css using el/jstl would also increase http requests since more files now. also separating the two would decrease maintainability since developers may find when they edit a css style, they have to check multiple files.

what is enterprise best pratices for this issue?

Posted by: mike at December 18, 2007 8:54 AM

Suppose the answer was to leave it in two files. Then someone would ask 15%, 20%, etc. There are too many variables to pinpoint the exact tradeoff point. What percentage of users have an empty cache vs. primed cache? What's the typical user's connection speed? How many page views per session? How many of the session's page views contain this CSS? How big is the CSS? Are there any other resources on the CSS's hostname (since only two downloads can happen in parallel for a single hostname)? On and on...

If this decision is important enough, and the answer is unclear, run a bucket test. For one set of users make the change and compare that to the control group. Who had faster response times?

My gut says if the CSS is >5K then split it across two files. Even better would be to put the 10% dynamic CSS in the actual HTML document, as opposed to a separate download.

-Steve

Posted by: Steve Souders at December 18, 2007 9:38 AM

REPOST (sorry it stripped my tags)

yeah im gonna try putting the dynamic parts in the JSP and splitting it.

btw i wanted to confirm, is it true parallel downloading stops when you :

1.) make a either a js or css request like
< script type="text/javascript" src="http://yui.yahooapis.com/2.3.1/build/yahoo/yahoo-min.js" >< /script >
or
< link rel="stylesheet" href="blah" type="text/css" / >

2.) put javascript and css on the page like
< style >
# blah {}
< /style>

or
< script>
var a=1;
< / script>

Posted by: mike at December 20, 2007 10:57 AM

External scripts block all downloads in IE and Firefox. External stylesheets block downloads in Firefox. Inline script and style blocks don't block in either.

-Steve

Posted by: Steve Souders at December 20, 2007 11:29 AM

In your example "instead of this"..."Do this", they appear exactly the same. If that was intentional, OK, but the instead of comment seems to imply a difference.

David

Posted by: david at January 14, 2008 8:46 AM

For developers who write web sites for customers: Recent analysis of a couple customer sites at my place of work suggest that Rule #1 is more important then Rule #8. We are finding that making HTTP requests are MUCH more expensive than the size of the data coming down. This is due to all the "stuff" in the middle (such as proxies, firewalls, reverse proxies, load balancers, etc...). For maintanability reasons, we need to keep our javascripts broken up into different files (it would be hard to support one massive JS file with 10000's of lines of code in it) so rolling everything into a single JS file will not be a good architecture from a development perspective.

We use SSI (Server-Side Includes) in order to simulate placing all the JS files inline with the rest of the HTML. When we use SSI, we see a speed increase that is 10-20 times faster than if we didn't do inlining (2 secs versus 20 secs).

The down side of inlining is that you are not leveraging your browsers cache. However, the speed increase for our customers far out-weights the cost of bandwidth for not being able to leverage the cache. Web site adoption is the key to a successful product...a fast and speedy first impression carries tremendously more weight than having to experience an extra bandwidth overhead of say 50K because each page will have the same javascript being downloaded again. Admittedly, this can be a problem for 56K modem users (but only those kinds of users with restrictive internet pipes)

SSI is an easy way to get the performance speed without having to change or move code around in your HTML files. An alternative would be dynamic generation of an "uber" JS file that gets physically created as part of a web site deployment strategy. This gives you the best-case scenario...
- One HTTP request
- Browser cache leveraged
- Retain JS file segmentation on the back-end for maintanability and risk management reasons.

Posted by: Mike at January 17, 2008 6:33 PM

What about websites with javascript served by ad servers. Each time a visitor refreshes the page a different ad is shown. How would caching work. As the owner of the website I obviously want to show as many ads as possible to each visitor. Are there any methods to increase page speed for pages with javascript supplied from a third party?
What about the little script from Google Analytics, cashing that would defeat the entire purpose? How do I ensure that I am optimizing my page load time?

Posted by: Don at March 6, 2008 2:28 PM

I am very interested inlining JS and CSS in the front page, but dynamically downloading the external files after the page has finished loading so that subsequent pages would reference the external files that are already be in the browser's cache.

Can someone show a clear example of how to do this?

Posted by: Stan at June 9, 2008 3:14 PM

Nice one. I have a doubt though. I tried out giving versions to js/css files like "abc.js?1.0". The problem is that sometime it works and sometime it doesnt. however when i try like "abc.js?1:0" it always works(atleast no failures till now).
Can anyone tell me what is the difference between these two...viz.."abc.js?1.0" and "abc.js?1:0" ..?

Posted by: Jonathan at June 20, 2008 8:59 AM

Posted by: Donnie at July 13, 2008 7:24 PM

Nice one. I have a doubt though. I tried out giving versions to js/css files like "abc.js?1.0". The problem is that sometime it works and sometime it doesnt. Rea33y g66d 5te0s, thx so mutch!

Posted by: K-fuel saver tablets at September 18, 2008 2:21 AM

Does anyone know how inline scripting compares to external files when the external files are cached at a CDN like Akamai? Do the HTTP Gets become fast enough for it to make sense not to use inline scripting. I am thinking about a scenario where the script is around 60K (30% of total content on the page) and the page is accessed only once by 95% of the users.

Posted by: stikoo at October 31, 2008 7:47 AM

Nice one. I have a doubt though. I tried out giving versions to js/css files like "abc.js?1.0". The problem is that sometime it works and sometime it doesnt. however when i try like "abc.js?1:0" it always works(atleast no failures till now).
Can anyone tell me what is the difference between these two...viz.."abc.js?1.0" and "abc.js?1:0" ..?

Posted by: rubbish clearance london at December 28, 2008 2:28 AM

I have a one page AJAX application, and I only use jQuery, so I inline the minified version into the page, but HTML Validator produce hundred warnings. Do you experience the same issue? Is this a bug within HTML Validator? Can we work around it?

Posted by: Khai Doan at July 24, 2009 2:24 AM

Post a comment

Comment Policy: We encourage comments and look forward to hearing from you. Please note that Yahoo! may, in our sole discretion, remove comments if they are off topic, inappropriate, or otherwise violate our Terms of Service. Fields marked with asterisk '*' are required.

Remember Me?

Subscribe

YDN Blog: Get Yahoo! Developer Network Blog on your personalized My Yahoo! home page.

Add To My RSS Feed

YDN Link Blog: Get Yahoo! Developer Network Linkblog on your personalized My Yahoo! home page.

Add To My RSS Feed

Recent Readers

Copyright © 2010 Yahoo! Inc. All rights reserved. Copyright | Privacy Policy

Help us continue to improve the Yahoo! Developer Network: Send Your Suggestions