Generate a Mirror | Mirror List

Google
 
  AddThis Social Bookmark Button

Anticipating a your site getting Slashdotted, or succuming to the Digg effect? Mirror your site for free with LynxCache.

 


Vitamin Features » Serving JavaScript Fast

mirror of http://www.thinkvitamin.com/features/webapps/serving-javascript-fast


    Vitamin Features Serving JavaScript Fast   

 

[1]

 

Home [2] Features [3] Training [4] Reviews [5] Interviews [6] Advisory board [7] Subscribe [8] About [9] Contact [10] Job Board [11]

 

FEATURES

 

Print Format [12] Email to a Friend [13]

 

WEB APPS [14] JAVASCRIPT [15] : SERVING JAVASCRIPT FAST [16]

 

Sunday, May 21st, 2006 Cal Henderson [17] Flickr [18] [19] [20]

 

The next generation of web apps make heavy use of JavaScript and CSS. We'll show you how to make those apps responsive and quick.

 

With our so-called "Web 2.0" applications and their rich content and interaction, we expect our applications to increasingly make use of CSS and JavaScript. To make sure these applications are nice and snappy to use, we need to optimize the size and nature of content required to render the page, making sure we're delivering the optimum experience. In practice, this means a combination of making our content as small and fast to download as possible, while avoiding unnecessarily refetching unmodified resources.

 

This is complicated a little by the nature of CSS and JavaScript resources. In contrast to image assets, CSS and JavaScript source code is very likely to change many times as time goes by. When these resources change, we need our clients to download them all over again, invalidating the version in their local cache (and any versions stored in other caches along the way). In this article, we'll look at ways we can make the whole experience as fast as possible for our users - the initial page load, subsequent page loads and ongoing resource loading as the application evolves and content changes.

 


I believe strongly in making things as simple as possible for developers, so we'll also be looking at ways we can set up our systems to automatically take care of these optimization issues for us. With a little up front work, we can get the best of both worlds - an environment that makes development easy with great end-user performance - all without changing the way we work.

 

MONOLITH

 

The old school of thought was that we could achieve optimal performance by combining multiple CSS and JavaScript files into fewer, larger blocks. Rather than having ten 5k JavaScript files, we combine them into a single 50k file. While the total size of the code is still the same, we avoid having the overhead associated with multiple HTTP requests. Each request has a setup and teardown phase on both the client and server, incurs request and response header size overhead, and resource overhead on the server side in the form of more processes or threads (and perhaps more CPU time for on-the-fly gzipped content).

 

The parellization aspect is also important. By default, both Internet Explorer and Mozilla/Firefox will only download two resources [21] from a single domain at once when using persistent connections (as suggested in the HTTP 1.1 spec [22], section 8.1.4). This means that while we're waiting to download those JavaScript files, 2 at a time, we're not loading image assets - the page our users see during the loading phase will be missing its images.

 

However, there are a couple of downsides to this approach. By bundling all of our resources together, we force the user to download everything up front. By chunking content into multiple files we can spread out the cost of loading across several pages, amortizing the speed hit across a session (or avoiding some of the cost completely, depending on the path the user chooses). If we make the first page slow to speed up subsequent pages, we might find that we have more users who never wait around to request a second page.

 

The big downside to the single file approach has not often, historically, been considered. In an environment where we will have to often change our resources, _any_ changes to a single-file system will require the client to re-download a copy of the entire CSS or JavaScript working set. If our application has a single monolithic 100k JavaScript source file, any tiny change to our code will force all clients to suck down the 100k all over again.

 

A SPLINTERED APPROACH

 

The alternative approach lies somewhere in the middle - we split our CSS and JavaScript resources into multiple sub-files, while at the same time keeping that number functionally low. This compromise comes at a cost - we need to be able to develop applications with our code split out into logical chunks to increase development efficiency, while delivering merged files for performance. With a few additions to our build system (the set of tools which turn your development code into production code, ready for deployment), this needn't be a compromise we have to make.

 

For an application environment with distinct development and production environments, you can use a few simple techniques to keep your code manageable. In your development environment, code can be split into many logical components to make separation clear. In Smarty [23] (A PHP templating language) we can create a simple function to manage the loading of our JavaScript:

 

SMARTY: {insert_js files="foo.js,bar.js,baz.js"} PHP: function smarty_insert_js($args){ foreach (explode(',', $args['files']) as $file){ echo "n"; } } OUTPUT:

 


So far, so easy. But then we instruct our build process to merge certain files together into single resources. In our example, imagine we merged foo.js and bar.js into foobar.js, since they are nearly always loaded together. We can then record this fact in our application configuration and modify our template function to use this information.

 

SMARTY: {insert_js files="foo.js,bar.js,baz.js"} PHP: # map of where we can find .js source files after the build process # has merged as necessary $GLOBALS['config']['js_source_map'] = array( 'foo.js' => 'foobar.js', 'bar.js' => 'foobar.js', 'baz.js' => 'baz.js', ); function smarty_insert_js($args){ if ($GLOBALS['config']['is_dev_site']){ $files = explode(',', $args['files']); }else{ $files = array(); foreach (explode(',', $args['files']) as $file){ $files[$GLOBALS['config']['js_source_map'][$file]]++; } $files = array_keys($files); } foreach ($files as $file){ echo "n"; } } OUTPUT:

 

The source code in our templates doesn't need to change between development and production, but allows us to keep files separated while developing and merged in production. For bonus points, we can write our merging process in PHP and use the same configuration block to perform the merge process, allowing us to keep a single configuration file and avoid having to keep anything in sync. For super-bonus points, we could analyze the occurrence of scripts and style sheets together on pages we serve, to determine which files would be best to merge (files that nearly always appear together are good candidates for merging).

 

For CSS, a useful model to start from is that of a master and subsection relationship. A single master style sheet controls style across your entire application, while multiple sub-sheets control various distinct feature areas. In this way, most pages will load only two sheets, one of which is cached the first time any page is requested (the master sheet).

 

For small CSS and JavaScript resource sets, this approach _may_ be slower for the first request than a single large resource, but if you keep the number of components low then you'll probably find it's actually faster, since the data size per page is much lower. The painful loading costs are spread out around different application areas, so the number of parallel loads is kept to a minimum while also keeping the resources-per-page size low.

 

COMPRESSION

 

When talk about asset compression, most people think immediately of mod_gzip [24]. Beware, however - mod_gzip is actually _evil_, or at the least, a resource hogging nightmare. The idea behind it is simple - browsers request resources and send along a header to show what kind of content encodings they accept. It looks something like this:

 

Accept-Encoding: gzip,deflate

 

When a server encounters this header, it can then gzip or deflate (compress) the content it's sending to the client, where the client will then decompress it. This burns CPU time on both the client and server, while reducing the amount of data transferred. All well and good. The way mod_gzip works, however, is to create a temporary file on disk in which to compress the source data, serve that file out, then delete it. For high volume systems, you very quickly become bound by disk IO. We can avoid this by using mod_deflate [25] instead (Apache 2 only), which does all the compression in memory - sensible. For Apache 1 users, you can instead create a RAM disk and have mod_gzip writes its temporary files there - not quite as fast as pure in-memory compression, but not nearly as slow as writing to disk.

 

Even so, we can avoid the compression overhead completely by pre-compressing the relevant static resources and using mod_gzip to serve people the compressed version where appropriate. If we add this compression into our build process, it all happens transparently to us. The number of files that need compressing is typically quite low - we don't compress images since we don't gain much, if any, size benefit (since they're already compressed) so we only need to compress our JavaScript and CSS (and any other uncompressed static content). Configuration options tell mod_gzip where to look for pre-compressed files.

 

mod_gzip_can_negotiate Yes mod_gzip_static_suffix .gz AddEncoding gzip .gz

 

Newer versions of mod_gzip (starting with version 1.3.26.1a) can pre-compress files for you automatically by adding a single extra configuration option. You'll need to make sure that Apache has the correct permissions to create and overwrite the gzipped files for this to work.

 

mod_gzip_update_static Yes

 

However, it's not that simple. Certain versions of Netscape 4 (specifically 4.06 to 4.08) identify themselves as being able to interpret gzipped content (they send a header saying they do), but they cannot correctly decompress it. Most other versions of Netscape 4 have issues with loading compressed JavaScript and CSS in different and exciting ways. We need to detect these agents on the server side and make sure they get served an uncompressed version. This is fairly easy to work around, but Internet Explorer (versions 4 through 6) has some more interesting issues. When loading gzipped JavaScript, Internet Explorer will sometimes incorrectly decompress [26] the resource, or halt compression halfway through, presenting half a file to the client. If you rely on your JavaScript working, you need to avoid sending gzipped content to Internet Explorer. In the cases where Internet Explorer _does_ receive gzipped JavaScript correctly, some older 5.x versions won't cache the file, regardless of it's e-tag headers.

 

Since gzip compression of content is so problematic, we can instead turn our attention to compressing content without changing its format. There are many JavaScript compression scripts available, most of which use a regular expression driven rule set to reduce the size of JavaScript source. There are several things which can be done to make the source smaller - removing comments, collapsing whitespace, shortening privately scoped variable names and removing optional syntax.

 

Unfortunately, most of these scripts either obtain a fairly low compression rate, or are destructive under certain circumstances (or both). Without understanding the full parse tree, it's difficult for a compressor to distinguish between a comment and what looks like a comment inside a quoted string. Adding closures to the mix, it's not easy to find which variables have a private lexical scope using regular expressions, so some variable name shortening techniques will break certain kinds of closure code.

 

One compressor does avoid this fate - the Dojo Compressor [27] (there's a ready-to-use version here [28]) works by using Rhino (Mozilla's JavaScript engine implemented in Java) to build a parse tree, which it then reduces before serializing it to a file. The Dojo Compressor can give pretty good savings for a low cost - a single compression at build time. By building this compression into our build process, it all happens transparently for us. We can add as much whitespace and as many comments as we like to our JavaScript in our development environment, without worrying about bloating our production code.

 

Compared to JavaScript, CSS is relatively simple to compress. Because of a general lack of quoted strings (typically paths and font names) we can mangle the whitespace using regular expressions. In the cases where we _do_ have quoted strings, we can nearly always collapse a whitespace sequence into a single space (since we don't tend to find multiple spaces or tabs in URL paths or font names). A simple Perl script should be all we need:

 

#!/usr/bin/perl my $data = ''; open F, $ARGV[0] or die "Can't open source file: $!"; $data .= $_ while ; close F; $data =~ s!/*(.*?)*/!!g; # remove comments $data =~ s!s+! !g; # collapse space $data =~ s!} !}n!g; # add line breaks $data =~ s!n$!!; # remove last break $data =~ s! { ! {!g; # trim inside brackets $data =~ s!; }!}!g; # trim inside brackets print $data;

 

We can then feed individual CSS files through the script to compress them like so:

 

perl compress.pl site.source.css > site.compress.css

 

With these simple plaintext optimizations we can reduce the amount of data sent over the wire by as much as 50% (depending upon your coding style - it might be much less), which can translate to a much faster experience for our users. But what we'd really like to do is avoid users having to even request files unless completely necessary - and that's where an intimate knowledge of HTTP caching comes in handy.

 

CACHING IS YOUR FRIEND

 

When a user agent requests a resource from a server for the first time, it caches the response to avoid making the same request in the future. How long it stores this response for is influenced by two factors - the agent configuration and any cache control response headers from the server. All browsers have subtly different configuration options and behaviors, but most will cache a given resource for at least the length of a session, unless explicitly told otherwise.

 

It's quite likely you already send out anti-caching headers for dynamic content pages to avoid the browser caching pages which constantly change. In PHP, you can achieve this with a pair of function calls:

 

Sounds too easy? It is - some agents will ignore this header under certain circumstances. To _really_ convince a browser not to cache a document, you'll need to be a little more forceful:

 

This is fine for content we don't want to be cached, but for content that doesn't change with every request we want to encourage the browser to cache it aggressively. The "If-Modified-Since" request header allows us to get part of the way there. If a client sends an "If-Modified-Since" header with its request, Apache (or your web server of choice) can respond with status code 304 ("Not Modified"), telling the browser that its cached copy of the file is already up to date. With this mechanism, we can avoid sending the contents of a file to the browser, but we still incur the overhead of an HTTP request. Hmmm.

 

Similar to the if-modified-since mechanism are entity tags. Under Apache, each response for a static resource is given an "ETag" header containing a checksum generated from the file's modified-time, size and inode number. A browser can then perform a HEAD request to check the e-tag for a resource without downloading it. E-tags suffer from the same problem as the if-modified-since mechanism - the client still needs to perform an HTTP request to determine the validity of the locally cached copy.

 

In addition, you need to be careful with if-modified-since and e-tags if you serve content from multiple servers. With two load-balanced web servers, a single resource could be requested from either server by a single agent - and could be requested from each at different times. This is great - it's why we load balance. However, if the two servers generate different e-tags or modified dates for the same files, then browsers won't be able to properly cache content. By default, e-tags are generated using the inode number of the file, which will vary from server to server. You can turn this off using a single Apache configuration option:

 

FileETag MTime Size

 

With this option, Apache will use only the modification time and file size to determine the e-tag. This, unfortunately, leads us to the other problem with e-tags, which can affect if-modified-since too (though not nearly as badly). Since the e-tag relies on the modified time of the file, we need those times to be in sync. If we're pushing files to multiple web servers, there's always a chance that the time at which the files are pushed are subtly different by a second or two. In this case, the e-tags generated by two servers will still be different. We could change the configuration to generate e-tags only from the file size, but this means that we'll generate the same e-tag if we change a file's contents without changing its size. Not ideal.

 

CACHING IS YOUR _BEST_ FRIEND

 

The problem here is that we are approaching the issue from the wrong direction. These possible caching strategies all revolve around the client asking the server if its cached copy is fresh. If we could notify the client when we change a file, it would know that its own cached copy was fresh, until we told it otherwise. But the web doesn't work that way - the client makes requests to the server.

 

But that's not quite true - before fetching any JavaScript or CSS files, the client makes a request to the server for the page which will be loading those files via or tags. We can use the response from the server to notify the client of any changes in those resources. This is all a little cryptic, so let's spell it out - if we change the filenames of JavaScript and CSS files when we change their contents, we can tell the client to cache every URL forever, since the content of any given URL will never change.

 

If we are sure that a given resource will never change, then we can send out some seriously aggressive caching headers. In PHP, we just need a couple of lines:

 

Here we tell the browser that the content will expire in 10 years (there are 315,360,000 seconds in 10 years, more or less) and that it can keep it around for 10 years. Of course, we're probably not serving our JavaScript and CSS via PHP - we'll address that in a few moments.

 

MISTAKES ABOUND

 

Manually changing the filenames of resources when the contents are modified is a dangerous task. What happens if you rename the file, but not the templates pointing to it? What happens if you change some templates but not others? What happens if you change the templates but don't rename the file? Most likely of all, what happens if you modify a resource but forget to rename it or change any references to it. In the best of these cases, users will not see the new content and be stuck with the old versions. In the worst case, no valid resource is found and your site stops working. This sounds like a dumb idea.

 

Luckily computers are really good at this sort of thing - dull repetitive tasks which need to be done exactly right, over and over again, when some kind of change occurs.

 

The first step in making this process as painless as possible is to realize that we don't need to rename files at all. URLs we serve content from and where the content is located on disk don't have to have anything to do with each other. Using Apache's mod_rewrite [29] we can create a simple rule to redirect certain URLs to certain files.

 

RewriteEngine on RewriteRule ^/(.*.)v[0-9.]+.(css|js|gif|png|jpg)$ /$1$2 [L]

 

This rule matches any URL with one of the specified extensions which also contains a 'version' nugget. The rule then rewrites these URLs to a path without the version nugget. Some examples:

 

URL Path /images/foo.v2.gif -> /images/foo.gif /css/main.v1.27.css -> /css/main.css /javascript/md5.v6.js -> /javascript/md5.js

 

With this rule in-place, we can change the URL (by changing the version number) without changing where the file lives on disk. Because the URL has changed, the browser treats it as a different resource. For bonus points, you can combine this with the script grouping function from earlier to produce a list of versioned tags as needed.

 

At this point, you might ask why we don't just add a query string to the end of the resource - /css/main.css?v=4. According the letter of the HTTP caching specification, user agents should _never_ cache URLs with query strings. While Internet Explorer and Firefox ignore this, Opera and Safari don't - to make sure all user agents can cache your resources, we need to keep query strings out of their URLs.

 

Now that we can change our URLs without moving the file, it would be nice to be able to have the URLs updated automatically. In a small production environment (or a development environment, for people with large production environments), we can do this really easily using a template function. This example is for Smarty, but applies equally well to other templating engines.

 

SMARTY: PHP: function smarty_version($args){ $stat = stat($GLOBALS['config']['site_root'].$args['src']); $version = $stat['mtime']; echo preg_replace('!.([a-z]+?)$!', ".v$version.$1", $args['src']); } OUTPUT:

 

For each linked resource, we determine the file's location on disk, check its mtime (the date and time the file was last modified on disk) and insert that into the URL as the version number. This works great for low traffic sites (where stat operations are cheap) and for development environments, but it doesn't scale well to high volume deployments - each call to stat requires a disk read.

 

The solution is fairly simple. In a large system we already have a version number for each resource, in the form of the source control revision number (you're already using source control, right?). At the point when we go to build our site for deployment, we simply check the revision numbers of all of our resource files and write them to a static configuration file.

 

We can then modify our templating function to use these version numbers when we're operating in production.

 

In this way, we don't need to rename any files, or even remember when we modify resources - the URL will be automatically changed everywhere whenever we push out a new revision - lovely. We're almost where we want to be.

 

BRINGING IT ALL TOGETHER

 

When we talked about sending very-long-period cache headers with our static resources earlier, we noted that since this content isn't usually served through PHP, we can't easily add the cache headers. We have a couple of obvious choices for dealing with this; inserting PHP into the process or letting Apache do the work.

 

Getting PHP to do our work for us is fairly simple. All we need to do is change the rewrite rule for the static files to be routed through a PHP script, then have the PHP script output headers before outputting the content of the requested resource.

 

Apache: RewriteRule ^/(.*.)v[0-9.]+.(css|js|gif|png|jpg)$ /redir.php?path=$1$2 [L] PHP: header("Expires: ".gmdate("D, d M Y H:i:s", time()+315360000)." GMT"); header("Cache-Control: max-age=315360000"); # ignore paths with a '..' if (preg_match('!..!', $_GET[path])){ go_404(); } # make sure our path starts with a known directory if (!preg_match('!^(javascript|css|images)!', $_GET[path])){ go_404(); } # does the file exist? if (!file_exists($_GET[path])){ go_404(); } # output a mediatype header $ext = array_pop(explode('.', $_GET[path])); switch ($ext){ case 'css': header("Content-type: text/css"); break; case 'js' : header("Content-type: text/javascript"); break; case 'gif': header("Content-type: image/gif"); break; case 'jpg': header("Content-type: image/jpeg"); break; case 'png': header("Content-type: image/png"); break; default: header("Content-type: text/plain"); } # echo the file's contents echo implode('', file($_GET[path])); function go_404(){ header("HTTP/1.0 404 File not found"); exit; }

 

While this works, it's not a great solution. PHP demands more memory and execution time than if we did everything in Apache. In addition, we have to be careful to protect against exploits made possible by sending us doctored values for the path query parameter. To avoid all this headache, we can have Apache add the headers directly. The RewriteRule directive allows us to set environment variables when a rule is matched, while the Header directive lets us add headers only when a given environment variable is set. Combining these two directives, we can easily chain the rewrite rule together with the header settings.

 

RewriteEngine on RewriteRule ^/(.*.)v[0-9.]+.(css|js|gif|png|jpg)$ /$1$2 [L,E=VERSIONED_FILE:1] Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE Header add "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

 

Because of Apache's order of execution, we need to add the RewriteRule line to the main configuration file (httpd.conf) and not a per-directory (.htaccess) configuration file, otherwise the Header lines get run first, before the environment variable gets set. The Header lines can either go in the main configuration file or in an .htaccess file - it makes no difference.

 

SKINNING RABBITS

 

By combining the above techniques, we can build a flexible development environment and a fast and performant production environment. Of course, this is far from the last word on speed. There are further techniques we could look at (separate serving of static content, multiple domain names for increased concurrency) and different ways of approaching the ones we've talked about (building an Apache filter to modify outgoing URLs in HTML source to add versioning information on the fly). Tell us about techniques and approaches that have worked well for you by leaving a comment.

 

READ MORE

 

Cal's new book, Building Scalable Web Sites [30], contains more tips and tricks to help you develop and manage the next generation of web applications.

 

Like this article? Digg it [31]!

 

Fuel [32] is a brand new affordable conference about powering your business with the web: London June 13

 

Join Jina Bolton, Jon Hicks, Larissa Meek, Daniel Burka and more for Future of Web Design [33], London April 17-18

 

Leave a response [34], or trackback [35] from your own site.

 

196 RESPONSES TO "SERVING JAVASCRIPT FAST"

 

alexander says (on May 22nd, 2006 at 7:54 am [36] )

 

I have noticed several sites using something like:

 

What technique is recommended for adding the unix timestamp, is it server-side reading the modification date of the file or something else? meneame.net says (on May 22nd, 2006 at 8:05 am [37] )

 

CóMO SERVIR JAVASCRIPT RáPIDO

 

Las nuevas aplicaciones web 2.0 tienden a incrementar el uso de Javascript considerablemente. Uno de los ingenieros principales que desarrollan Flickr presenta en este artículo las claves para servir Javascript rápido. Carnet Web de Pascal says (on May 22nd, 2006 at 10:08 am [38] )

 

SERVIR DU JAVASCRIPT RAPIDEMENT

 

Un intéressant article de Cal Henderson (développeur de Flickr) :

 

Serving JavaScript Fast

 

Il y explique tout un tas de techniques côté serveur pour améliorer la rapidité d'un site dépendant beaucoup de javascript/css, rien de révolutionnaire Robertas Aganauskas says (on May 22nd, 2006 at 11:21 am [39] )

 

Thanks Cal, that really helped a lot (especially the idea of elegant versioning files). Max says (on May 22nd, 2006 at 1:10 pm [40] )

 

While these are great recommendations for an Apache/PHP environment, I would've liked to see more cross platform solutions, to include .NET/IIS as well. Great nevertheless. Stefan Hayden says (on May 22nd, 2006 at 1:29 pm [41] )

 

According the letter of the HTTP caching specification, user agents should never cache URLs with query strings. While Internet Explorer and Firefox ignore this, Opera and Safari don’t

 

I'm confused about which browsers you say DO cache files with query strings? All the tests I've done show that in both IE and Firefox adding a query string does infact force the browser to re-download the css file. And that if the current query string matches the previous query string then the file stays cached.

 

you are saying it's Opera and Safari this does not work on? Cal Henderson says (on May 22nd, 2006 at 4:33 pm [42] )

 

Stefan:

 

No browser will treat URLs with different query strings as the same. "foo.css?v=1 and "foo.css?v=2 will always cause a refetch.

 

However, Safari and Opera (most, if not all versions) will not cache any URL with a query string - it will treat two URLs with the _same_ query string as if they were _different_ URLs. If a first page requests "foo.css?v=1 and a second page _also_ requests "foo.css?v=1, the first request will not be cached. Mandy Singh says (on May 22nd, 2006 at 7:00 pm [43] )

 

Nice Article!

 

Just want to know more about the gzip related problem. Is it seen mostly with .js & .css file on Internet Explorer?

 

Would it be any better if gzip for .js & .css files was turned off (I know half the code is going to be in them) but at least the html pages would be served faster (never mind the includes which are anyway going to be cached).

 

Let me know your thoughts.

 

Thanks, Mandy. Cal Henderson says (on May 22nd, 2006 at 8:49 pm [44] )

 

Mandy:

 

It's _mostly_ seen with JavaScript and CSS, but can happen with HTML too. In this case it's a lot more obvious to the user that something's gone wrong so there's a greater change they'll reload and clear the issue themselves. With JavaScript, if a bad version of a file gets cached then the user may never realize it's not working as expected. Pig Pen - Web Standards Compliant Web Design Blog Blog Archive Serving JavaScript Fast says (on May 22nd, 2006 at 9:22 pm [45] )

 

[] Serving JavaScript Fast by Cal Henderson over on Vitamin. [] Keith says (on May 22nd, 2006 at 10:47 pm [46] )

 

Thank you Cal, Great Article. AJAX道 web应用加速技巧 says (on May 23rd, 2006 at 12:46 am [47] )

 

[] http://www.thinkvitamin.com/features/webapps/serving-javascript-fast 归类于: Javascript, 编程例子, PHP, Perl by -- gaoliang @ 8:45 am [] Nicolai says (on May 23rd, 2006 at 3:48 am [48] )

 

- Why not use mod_negotiation for compression? That will allow you to use pre-compressed files and avoid per-request on-the-fly compression. You can automate this and use the most expensive/effective compression level (gzip -9 foo).

 

- Separate static content, dynamic content, and database onto separate machines.

 

- Serve static content from a machine with lots of RAM to allow OS- or server-level file caching. Check out a built-for-speed server like lighttpd.

 

- Compile a stripped-down version of your Web server using only the modules you need.

 

- For frequently-called, brain-dead utility work like "Bringing it all together", avoid PHP like the plague. Write it in C using FastCGI.

 

- For big PHP, use the Zend Optimizer. Check out the PHP5 function benchmarks at http://byster.net/?page_id=48

 

- All the usual stuff: don't follow symlinks, don't use .htaccess files, don't resolve client hostnames (move the logs to another machine and batch it later), etc..

 

- If you use SSL, buy a dedicated hardware SSL device that offloads crypto processing from the servers to it.

 

- When linking to directories, add the trailing slash. i.e. http://foo.com/bar/ rather than http://foo.com/bar. This avoids an HTTP redirect, which results in an unncessary HTTP transaction. Emergent Properties Blog Archive How To Speed Up Your Web App says (on May 23rd, 2006 at 4:41 am [49] )

 

[] read more | digg story [] Bizarro says (on May 23rd, 2006 at 6:28 am [50] )

 

No offense dude I know that you work on Flickr but this is the most convoluted, bizarre set of recommendations I have ever seen. Is this really workable in real life? It seems like a complicated process that could break at any stage. Thanks for sharing the insanity though Andy Kant says (on May 23rd, 2006 at 6:46 am [51] )

 

Great article, I will make sure to use your recommendations in the future. Thanks! ajaxDNA says (on May 23rd, 2006 at 7:09 am [52] )

 

[] A very good article from Cal Henderson of Flickr/Yahoo. [] Sam Minnee says (on May 23rd, 2006 at 7:16 am [53] )

 

Bizarro: The recommendations look like they're very tightly bound to the author's development workflow. So, while it may be byzantine to have to manually keep this stuff in check, if it fits into the way you normally go about building applications, then it's all good.

 

On the flip side, the author's done a good job of explaining his motivations for all the pieces, so we can all go and make use of the same ideas in our own applications, though maybe in different ways. All Dugg Blog Archive How To Speed Up Your Web App says (on May 23rd, 2006 at 9:12 am [54] )

 

[] The next generation of web apps make heavy use of JavaScript and CSS. This article, by the lead developer of Flickr, shows you how to make those apps responsive and quick.read more | digg story Share and Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages. [] [[ the sirens of titan ]] Blog Archive links for 2006-05-23 says (on May 23rd, 2006 at 9:21 am [55] )

 

[] Vitamin Features » Serving JavaScript Fast js/css caching tips (tags: javascript optimization development webdev web2.0 ajax) Posted by geekfreak Filed in Bookmarks [] Kim says (on May 23rd, 2006 at 10:04 am [56] )

 

Using mod_rewrite to hide version numbers is a bad thing. mod_rewrite requires a lot of ressources.

 

A better solution is using symlinks on the web server. Richard says (on May 23rd, 2006 at 11:39 am [57] )

 

I was looking at a simliar article yesterday, I guess this guy has copied a lot of content from this page.

 

http://vivekjishtu.blogspot.com/2006/04/speed-up-your-ajax-based-webapps.html 26 Miles Serving JavaScript Fast says (on May 23rd, 2006 at 12:52 pm [58] )

 

[] Read more at Thinkvitamin.com. Posted by Matt | May 23, 2006 | [] Cal Henderson says (on May 23rd, 2006 at 3:42 pm [59] )

 

Nicolai: Why use mod_negotiation (which gets measureably slower with Multiviews turned on) when the latest version of mod_gzip does exactly that, but with the added ability to freshen pre-compressed files as needed? As for recommending writing the braindead part in C, if you read that section carefully I suggest you use mod_rewrite and mod_headers which are already written in C and well optimized. The rest of your recommendations, while great, are all server performance, which we're not talking about here and is already very well covered elsewhere.

 

Bizarro: Can you suggest any part of it that would actually break? It's neither fragile nor complicated - we change URLs pointing to files. By buiilding it in at the template level it doesn't require us to think about it at all once it's been set up. It's working every day for hundreds of millions of pages - not just Flickr, but many large applications. Akamai's Edge Platform uses a very similar technique.

 

Kim: It's a myth that mod_rewrite is a really poor performer, but that's besides the point - there's a much greater issue with SymLinks. Ignoring the case of a development environment, imagine you had 10 JavaScript files and each of them (after some time) had been through one hundred revisions. Each time we deploy the app, we need to create 1000 symlinks. Depending on our the file system we're using, seek time can increase linearly with the number of files per directory. The time to create all of these symlinks is non-trivial too. We could rely on only symlinking the current revision and letting a 404 handler clean up the rest, but that seems messy to me, compared to the mod_rewrite option.

 

Alan says (on May 23rd, 2006 at 4:03 pm [60] )

 

Very excellent article, particularly the attention paid to the REALITIES of mod_gzip/mod_deflate and browser caching behavior when attaching query strings. Recently I've been fighting both battles at work, and it'll be nice to have a clear, well written resource to point to. Nicolai says (on May 23rd, 2006 at 4:29 pm [61] )

 

Sorry, but isn't this whole thing about server performance?

 

_Why use mod_negotiation (which gets measureably slower with Multiviews turned on) when the latest version of mod_gzip does exactly that, but with the added ability to freshen pre-compressed files as needed?_

 

Sorry, I guess I didn't read that carefully enough. That's excellent news! Since there's no need to use MultiViews in mod_negotiation to accomplish this, though, it may still be faster. Auto-freshen is a really nice feature from a developer standpoint, but it may slow it down a bit by doing a stat-and-compare for each request. I don't know for sure, though, I'll look at the source and see exactly what it's doing.

 

_As for recommending writing the braindead part in C, if you read that section carefully I suggest you use mod_rewrite and mod_headers which are already written in C and well optimized._

 

I agree, that's the way to go! But if you can't run Apache or an httpd that can do this natively in-process, C+FastCGI is a much more efficient alternative than PHP.

 

_The Header lines can either go in the main configuration file or in an .htaccess file - it makes no difference._

 

While this is true in terms of the resulting functionality, it's misleading in terms of performance. Using .htaccess files requires Apache to look for, open, read, close, parse, and compile it for every single request, which results in a significant speed penalty on a loaded server. (As you said, "This works great for low traffic sites (where stat operations are cheap) and for development environments, but it doesn’t scale well to high volume deployments - each call to stat requires a disk read."-then add a bunch of work on top of that.)

 

_It’s a myth that mod_rewrite is a really poor performer_

 

It doesn't _have_ to be, but it certainly can. Any use of regular expressions is going to cause a bit of a hit-pattern matching is not exactly a speedy operation. But you can make it much, much worse by writing your regular expressions badly. Use greedy operators (*) or specify more of the pattern than you need to and watch the performance plummet! Cal Henderson says (on May 23rd, 2006 at 4:40 pm [62] )

 

Nicolai: All excellent points. When I said this wasn't about server performance, I meant that we're looking at client performance as the main goal. Adding 10ms on the server isn't noticeable, but avoiding entire requests makes a big impact for the client. Unless you're serving A LOT of pages, server optimization can be a secondary activity. Even for small traffic applications, making some of the changes I talked about will make the user experience faster.

 

But yes, avoiding .htaccess files can give you a good speed boost, especially for deeply-nested webroots. Slashe says (on May 23rd, 2006 at 11:11 pm [63] )

 

Great article, I've just implemented some of the ideas and I'm already seeing a difference.

 

Note: I think your perl script is missing some slashes. jon says (on May 24th, 2006 at 12:30 am [64] )

 

how about setting a cache expiry date for the file, and then on that date sending/updating the file (most probably the .js) ?

 

if this is workable.wouldn't this be the ideal solution ? links for 2006-05-24 at leron's crib says (on May 24th, 2006 at 3:18 am [65] )

 

[] Vitamin Features » Serving JavaScript Fast via digg, tips for js & css performance optimization (tags: ajax compression css development performance php programming web2.0) [] Who Cares? How To Speed Up Your Web App says (on May 26th, 2006 at 1:57 am [82] )

 

[] The next generation of web apps make heavy use of JavaScript and CSS. This article, by the lead developer of Flickr, shows you how to make those apps responsive and quick. Link [] 94smart's Blog 接着讲Flickr的八卦 says (on May 26th, 2006 at 9:15 am [83] )

 

[] 前两天,顺着DBA的Flickr 的开发者的 Web 应用优化技巧,找到了Cal Henderson写的Serving JavaScript Fast,又让我窥探到Flickr的些些技术内幕,Flickr用的模板居然是SMARTY,这个之前普遍被人诟病的模板系统。 [] penk - Keep on rockin' in the free world Blog Archive 本日書籤 says (on May 30th, 2006 at 8:29 pm [90] )

 

[] http://www.thinkvitamin.com/features/webapps/serving-javascript-fast [] COLD CASE Blog Archive How To Speed Up Your Web App says (on June 14th, 2006 at 2:58 pm [116] )

 

[] read more | digg story Explore posts in the same categories: coldcase [] Yoann Boukredine says (on June 16th, 2006 at 10:12 am [117] )

 

Have a look at that great utilities :

 

http://hometown.aol.de/_ht_a/memtronic/

 

http://www.syntropy.se/?ct=downloads&target=jcefree

 

http://svn.dojotoolkit.org/dojo/trunk/buildscripts/lib/

 

Real solution : obfuscate and pre-compression (small name in variable etc) :)

 

Yoann! dandyna says (on June 18th, 2006 at 2:45 pm [118] )

 

This is a real useful article to me who's beginning with javascript selva says (on June 24th, 2006 at 11:36 am [119] )

 

hai henderson, Your tips for the java script loading is very good. but i need code exaple for jsp based examples to merge files,etc.. You have descriped everything in PHP.. Try to give in JSP also.. I realy need that.. Danny says (on July 18th, 2006 at 5:57 pm [120] )

 

Email to a Friend [121] is not validating webmasternewsblog.com Blog Archive says (on July 25th, 2006 at 6:19 pm [122] )

 

[] Speed up your JavascriptVitamin has a good article about how to optimize your Javascript for speed and efficiency, as old techniques won't fly in a "Web 2.0 world. Cal Henderson's best practices include compression, caching, and letting PHP or other server-side technologies do some of the work. [] De cómo comprimir ficheros javascript - Scriptia says (on July 30th, 2006 at 7:31 pm [123] )

 

[] En Serving JavaScript Fast, Carl Herlson, de Flickr, habla largo y tendido sobre diferentes métodos para acelerar la carga de scripts y hojas de estilo (combinación, compresión, cacheado). [] Suave's Blog Web Cache Tutorial says (on August 9th, 2006 at 9:40 am [124] )

 

[] Serving Javascript Fast [] auto says (on October 22nd, 2006 at 3:07 pm [134] )

 

Appreciate it men! Ed Eliot says (on October 31st, 2006 at 1:45 pm [135] )

 

An interesting read. I'd been thinking about the possibility of using mod rewrite to version JS and CSS files so it's great to see that thinking re-enforced here.

 

If memory serves me right IE actually only downloads one file at a time when it's downloading JavaScript (two for everything else) - not sure about other browsers. The adverse effect of multiple JavaScript file downloads is therefore amplified so unless your JS is really huge it I think it may still be beneficial to download one file containing everything. Martin says (on November 8th, 2006 at 11:14 pm [136] )

 

RFC 2616 (HTTP 1.1) says:

 

To mark a response as "never expires", an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.

 

And by the way, with mod_expires it’s very easy to set the expiration time. Ferienhaus Ostsee says (on November 24th, 2006 at 10:31 am [137] )

 

If memory serves me right IE actually only downloads one file at a time when it’s downloading JavaScript (two for everything else) - not sure about other browsers. The adverse effect of multiple JavaScript file downloads is therefore amplified so unless your JS is really huge it I think it may still be beneficial to download one file containing everything. Ignacio says (on November 24th, 2006 at 3:43 pm [138] )

 

Me resulta muy interesante este articulo, pero mi ingles no llego a comprender muy bien y tengo una mezcla de que es lo que hay que hacer para poder hacer funcionar esto, nadie conoce un articulo traducido de esto? o algun ejemplo andando sobre esto? Paul Loy says (on November 29th, 2006 at 9:00 pm [139] )

 

What Ferienhaus says is irrelevant. If IE does only download one javascript file at a time it's will take virtually the same time to download several smaller javascripts sequentially as it would to download one big huge one.

 

The benefits of lots of small files is that each page might not actually need ALL the javascript so you can optimise the amount of javascript you send to the browser. XUMADESIGNS Blog Archive Think Vitamin says (on January 1st, 2007 at 7:44 am [140] )

 

[] Thinkvitamin , bu siteye nerden rastladığım hakkında pek fikrim yok ancak oldukça hoş makaleler bulunmakta.Yazar kadrosu oldukça geniş ve profesyonel.Aslında o kadar çok güzel bölümü varki burda yazmak yerine sizlerin gezmesini tavsiye ederim.Bu yazıyı yazarken Cal Henderson'un Serving JavaScript Fast bu yazısını okumaktaydım ve oldukça güzel bir yazı olduğunu söyleyebilirim. [] mainzBlog says (on January 8th, 2007 at 10:26 pm [141] )

 

AJAX PATTERNS: ON-DEMAND JAVASCRIPT

 

Heute hatte ich das Problem: Wie bring ich Javascript-Code möglichst effizient in einer Ajax-Anwendung - das heißt viele verschiedene Javascript-Dateien - zur Ausführung im Browser, ohne dass dieser den Hitzetod durch Überarbeitung stirbt. (Vom gl Joseph Smarr Fixing eval() to use global scope in IE says (on January 31st, 2007 at 5:23 pm [142] )

 

[] When we built the first version of the new site, we combined all the JavaScript into one giant file as part of our deployment process. The total codebase was huge and it had the predictable effect that initial page-load time was terrible because the user's CPU was solidly spiked for several seconds while the poor browser choked through the massive amount of code it had to parse. So we started loading a lot of our code on-demand (packaging it into several logical chunks of related files and using dojo's package/loader system to pull in the code as needed). [] Speed Up Your Javascript Load Time | BetterExplained says (on February 22nd, 2007 at 6:33 am [143] )

 

[] Think vitamin: Serving Javascript Fast Posted February 21, 2007, under General Tags: browser, cache, compress, javascript, load, performance, programming, speed, Web Related Posts: [] Faster Page Loading - Professional PHP says (on February 28th, 2007 at 3:58 am [144] )

 

[] Cal Henderson of Flickr also takes up this topic in serving JavaScript fast. He goes into more depth about the issue of à la carte external objects versus aggregated external objects as well as covering compression and caching issues with examples in PHP. [] dobby says (on March 15th, 2007 at 9:00 pm [145] )

 

it is a top site Bodo says (on March 16th, 2007 at 12:41 pm [146] )

 

The comments are very helpful.Each one hat it's own experience by optimizing homepages. It’ a neverending story to optimize websites. Bob from Germany weser Nienburg Chad's dailies Blog Archive links for 2007-03-25 says (on March 25th, 2007 at 11:29 pm [147] )

 

[] Serving JavaScript Fast (tags: javascript articles webdev) [] Archive Faster Page Loads With Image Concatenation says (on May 8th, 2007 at 2:19 pm [157] )

 

[] Here's an interesting idea. In the same way that you can automatically compile multiple CSS and JavaScript files for a speed boost you can concatenate images. The file and HTTP request savings are obvious, but this method introduces a few CSS questions. Not impossible to overcome, but you need to be careful. [] vândpupăză Blog Archive Succesul este cel mai mare inamic al lui GetLoaded.ro1 says (on May 21st, 2007 at 8:45 pm [158] )

 

[] Serving JavaScript Fast [] vândpupăză Blog Archive Succesul este cel mai mare inamic al lui GetLoaded.ro says (on May 21st, 2007 at 8:45 pm [159] )

 

[] Serving JavaScript Fast [] Vitamin Features » Serving JavaScript Fast says (on June 10th, 2007 at 4:16 pm [160] )

 

 

[] http://www.thinkvitamin.com/features/webapps/serving-javascript-fast "The next generation of web apps make heavy use of JavaScript and CSS. We’ll show you how to make those apps responsive and quick."Tags: javascript, optimization, ajax, css, performance, development, apache, architecture(del.icio.us history) [] Chirru Blog Archive get subversion revision-number in a django-project says (on June 16th, 2007 at 9:17 am [161] )

 

[] Udi wrote: > Mind if I ask why? > i've got the idea from here: http://www.thinkvitamin.com/features/webapps/serving-javascript-fast the idea is that you serve all your media files (js/css/png/jpg) at urls that contain for example the svn version number, like: /media/1432/js/form.js and you setup your webserver to send such headers along the file which says that the file does not need to be re-fetched for a very long time (let's say a year). and when you release a new version of your program, then, because the version-number has changed, all your media-urls change. but it's much better described in the article. btw. for the reference, i abandoned the "svnversion" approach. it produces some funny version numbers when you use svn:externals, so i went with "svn info" and extracting the version-number from there. and, for now i decided that i will not do it at the startup, but will do it at release-time (so i will extract the version-number at the release-time, save it to let's say revision.py, and import it into settings.py). gabor [] Thomas Erichson says (on June 21st, 2007 at 6:34 pm [162] )

 

Hi there, nice website, well done, keep on doing so , with kind regards from germany Andy says (on June 21st, 2007 at 9:26 pm [163] )

 

We've found that body onload is essential in IE for dealing with what we suspect are gzip issues for javascript, also, not forgetting that any DOM code must wait for DOM/page rendering to complete anyway.Onload certainly fixed issues we were having in this area.

 

The browser processes javascript and css synchronously, hence, this is probably the rational behind a synchronous approach to loading resources of these types.

 

Also, I'm thinking what is the performance of gzip when comparing CPU time, file size and http savings. Below a certain threshold gzip isn't worthwhile - and I believe is configurable to prevent on-the-fly compression below a certain file size. Above that however, I believe gzip becomes very efficient. I'll head off now and try to find some research on this.

 

This has prompted me to run up some stats on our platform to compare page views with hits on our assets boxes - in other words, are we getting a good saving from GET caching.

 

Useful stuff, thanks. Carol Ballontiere says (on July 10th, 2007 at 8:07 am [164] )

 

Hello, super website here, well done, and thank you for all the useful links and hints. Kilburn says (on July 11th, 2007 at 9:47 am [165] )

 

RewriteRule ^/(.*.)v[0-9.]+.(css|js|gif|png|jpg)$ /$1$2 [L]

 

I think there's a little error in this regexp. The highlighted dot should have a backslash to escape it, otherways you're matching any character here, meaning that ie. this would be a non-desired match:

 

http://domain.tld/css/main.view.css Serving JavaScript Fast [REF] says (on July 13th, 2007 at 3:19 pm [166] )

 

[] Link [] Tims Blog Blog Archive Cant See Anything in URL Bar says (on July 13th, 2007 at 6:31 pm [167] )

 

[] serving javascript fast [] All in a days work says (on July 23rd, 2007 at 2:23 am [168] )

 

[] Serving JavaScript Fast - A splintered approach The alternative approach lies somewhere in the middle - we split our CSS and JavaScript resources into multiple sub-files, while at the same time keeping that number functionally low. [] beer2beer Article minify: Sirviendo javascript says (on July 23rd, 2007 at 8:00 pm [169] )

 

[] Antes de pasarme a minify, usaba una solución homebrew inspirada en el artículo de recomendada lectura "Serving Javascript fast" de Cal Henderson, desarrollador de flickr. Básicamente usaba ShrinkSafe para comprimir Javascript estáticamente (es decir, no bajo demanda), y PHP muy al estilo de minify pero más simple, para servir via mod_rewrite todo el contenido .js y .css de la aplicación, añadiéndole cache vía servidor. E iba bien, pero lo de combinar los archivos en uno me llamó la atención y la verdad es que minify va mejor! [] Patrick Whittingham says (on July 25th, 2007 at 7:17 pm [170] )

 

What about IIS 5,6,7 or does one do it on the application server level (ie., .Net / Java / cfmx) ? Rainbow in the AJAX Toilet says (on July 26th, 2007 at 12:00 pm [171] )

 

[] http://www.thinkvitamin.com/features/webapps/serving-javascript-fast [] 万用表 says (on July 28th, 2007 at 1:06 pm [172] )

 

nice 万用表 says (on July 28th, 2007 at 1:08 pm [173] )

 

http://www.yiqiei.cn Client side web site performance — onenaught.com says (on August 6th, 2007 at 8:04 am [174] )

 

[] Serving JavaScript fast from Vitamin. (Lots of good stuff here. See also the note about Apache's mod_gzip and mod_deflate. In short, use mod_deflate if you can.) [] Web site performance: Expires Header — onenaught.com says (on August 7th, 2007 at 8:30 pm [175] )

 

[] Cal Henderson, Serving JavaScript Fast, May 21, 2006 [] del.icio.us Cool Stuff On Web Developement says (on August 11th, 2007 at 1:14 am [176] )

 

[] Vitamin Features ? Serving JavaScript Fast - The next generation of web apps make heavy use of JavaScript and CSS. We?ll show you how to make those apps responsive and quick. [] Amit says (on August 15th, 2007 at 10:25 pm [177] )

 

Cal,

 

How well does Smarty perform on a large server load as a program like Flickr has? I've been hearing more good things about the Blitz templating system for PHP over that of Smarty. Scriptaculous Accordion with XHR Support Clown Shoes says (on September 5th, 2007 at 10:10 pm [178] )

 

[] // accordion.js v1.0 // // Copyright (c) 2007 stickmanlabs // Author: Kevin P Miller | http://www.stickmanlabs.com // // ListScroller is freely distributable under the terms of an MIT-style license. // // I don't care what you think about the file size // Be a pro: // http://www.thinkvitamin.com/features/webapps/serving-javascript-fast // http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files // [] Brett says (on September 22nd, 2007 at 3:11 am [179] )

 

Hello,

 

Excellent article. Very informative.

 

Since you mentioned Smarty and caching of CSS/JS, I thought I'd mention an extension I've made called SmartyDocB which lets you add scripts or CSS from within any template and have it shuffled off into one site-wide CSS or JS file (or shuffle it off to specifically designated files, which might suit the approach of dividing the files slightly), with comments automatically added around the injected content to indicate the source of the template (so when you are looking at the site-wide file, you know where the content came from).

 

This approach, I believe, is much more intuitive and handy, as you can store and edit such information alongside the HTML/XML for which it was most relevant, while still taking advantage of browser-caching and a global view of your scripts/styles. You can also manually edit these auto-generated site-wide or almost-site-wide files as long as you avoid editing within the auto-generated blocks.

 

To avoid live file rewriting on each page request, the system allows one through the API or optionally through a GET request to force a rewrite of all template content.

 

Documentation is at http://smartydocb.sourceforge.net/docs/documentation.xml (large file) and the code is at http://sourceforge.net/projects/smartydocb

 

Feedback is most welcome (even though my health limits how much time I can contribute to the project). .stron Sztuka optymalizacji. Podsumowanie. says (on September 25th, 2007 at 9:52 pm [180] )

 

[] Analogiczny problem dotyczy liczby zewnętrznych skryptów. Również w tym przypadku można zrealizować zadanie jednym zapytaniem. Bardzo obszernie i szczegółowo opisuje tą metodę Cal Henderson w artykule Serving JavaScript Fast. Artykuł zawiera ponadto przykłady programowego keszowania i kompresowania z użyciem funkcji PHP. [] Serving JavaScript Fast at davidbisset.com says (on September 29th, 2007 at 4:03 pm [181] )

 

[] Tips when working with big javascript libaries. the source digg_url='http://www.davidbisset.com/3452/serving-javascript-fast/'; digg_skin = 'button'; digg_bgcolor = '#FFFFFF'; digg_title = 'Serving JavaScript Fast'; digg_bodytext = ''; digg_topic = ''; Powered by Gregarious (41) Share This [] google reklam says (on October 8th, 2007 at 10:12 am [182] )

 

spasiwa Geekularity Magnolia Bookmarks says (on October 14th, 2007 at 7:01 am [183] )

 

[] Vitamin Features » Serving JavaScript Fast [] IPSOJOBS Blog Cache and GZIP your javascripts and CSSs files to speed up your site says (on October 15th, 2007 at 8:32 am [184] )

 

[] Good introduction to the problem of speeding up the webpages through caching and zipping javascripts Serving Javascript Fast [] prez says (on October 16th, 2007 at 9:43 am [185] )

 

Katalog stron says (on October 19th, 2007 at 8:05 am [186] )

 

Nice article. Mariachi Mike says (on October 23rd, 2007 at 10:21 am [187] )

 

Anybody know if there's a way to retrieve revision numbers by file with StarTeam? We need that in order to be able to enable far-future headers and automate the changes. Tom says (on October 23rd, 2007 at 3:06 pm [188] )

 

it's a great article and a good Site,Thx. Bye TOM YSlow - a nice performance plugin to Firebug - Robert's talk says (on October 31st, 2007 at 10:27 am [189] )

 

[] Serving JavaScript Fast - Nitty gritty details [] Learning AJAX Javascript by Example - Tutorials, Source-Code and Documentation | WebWolf Blog says (on January 27th, 2008 at 11:32 pm [210] )

 

[] Serving JavaScript Fast "With our so-called "Web 2.0 applications and their rich content and interaction, we expect our applications to increasingly make use of CSS and JavaScript. To make sure these applications are nice and snappy to use, we need to optimize the size and nature of content required to render the page, making sure we're delivering the optimum experience. In practice, this means a combination of making our content as small and fast to download as possible, while avoiding unnecessarily refetching unmodified resources." [] Jordi Hernandez says (on February 6th, 2008 at 10:02 am [211] )

 

There is an open source java tool which allows to easily implements all the optimization techniques described in this article while easing the development process. The library in question is Jawr [212], and basically it helps develop java web apps with heavy use of javascript. It does so by allowing you to split the .js codebase in as many files and directories as desired, without compromising page loading times. In fact, it will improve loading times since it will join the files into one or several bundles (which is easily configurable), and afterwards the bundles will be minified and gzipped. This way you can have a nicely modularized codebase that is easy to mantain instead of a couple of huge javascript files. Jawr has a development mode in which instead of the bundles, you get each member separately and with no minification, so you can use an exploded war directory and test changes on the fly. All without having to change the JSPs you are testing. Finally, you get the same advantages (modularization and compression) for CSS files. Chat Muhabbet Sohbet says (on February 6th, 2008 at 8:02 pm [213] )

 

Thank You ! Web Development 2.0 Blog Archive Faster Page Loading says (on February 9th, 2008 at 9:00 am [214] )

 

[] Cal Henderson of Flickr also takes up this topic in serving JavaScript fast. He goes into more depth about the issue of à la carte external objects versus aggregated external objects as well as covering compression and caching issues with examples in PHP. [] WebHelperMagazine.com Blog Archive Learning AJAX and Javascript says (on February 14th, 2008 at 4:21 pm [215] )

 

[] Serving JavaScript Fast "With our so-called "Web 2.0 applications and their rich content and interaction, we expect our applications to increasingly make use of CSS and JavaScript. To make sure these applications are nice and snappy to use, we need to optimize the size and nature of content required to render the page, making sure we're delivering the optimum experience. In practice, this means a combination of making our content as small and fast to download as possible, while avoiding unnecessarily refetching unmodified resources." [] anglictina says (on February 17th, 2008 at 6:11 pm [216] )

 

This look very cool, thank you Samurai says (on February 29th, 2008 at 11:30 pm [217] )

 

When sending the headers for these javascript/css files to keep them cached for as long as possible: would I set these headers in the page that uses them (for example index.php) or in the actual javascript/css file using php? Cal Henderson says (on March 3rd, 2008 at 12:36 am [218] )

 

When serving the js/css files. you can do that by serving them through php and adding the headers there, or (better) use apache config settings to send those headers directly Serving JavaScript Fast : iNetVista says (on March 5th, 2008 at 6:27 pm [219] )

 

[] http://www.thinkvitamin.com/features/webapps/serving-javascript-fast [] Daniel says (on March 13th, 2008 at 3:08 pm [220] )

 

What about versioning images inside css files? When I have something like this: background-image: url(../../image/admin/list_toolbar_bg.gif); gerard says (on March 20th, 2008 at 5:23 pm [221] )

 

This is a great article. Just found it via highscalability.com, and is still relevant even tho it is 2 yrs. old.

 

I'll contribute one big piece that we do differently, and it will help @daniel's problem.

 

 

We basically do everything mentioned in this article, although when it comes to filenames, instead of messing with rewriting or filtering URL's, our build process actually _copies_ our static content to a second location, _renaming_ them with their version numbers.

 

Now that we know how the original files map to their renamed versioned copies, we basically do a global regexp find-and-replace in our template files and CSS files. When the end-user requests the versioned file, there is no URL rewriting, because the request is for a real file.

 

So in @daniel's example, "url(../../image/admin/list_toolbar_bg.gif" becomes "url(../../image/admin/list_toolbar_bg.v6.gif"

 

Of course, we had some gotcha's with our regexp replace, which is why I'm considering using DOM instead.

 

The job takes a while, but that's ok since it's offline and we build continuously.

 

Additional bonus: when we copy CSS and JS, we can combine and minify them at this point. Additional bonus 2: when we replace the filenames in our templates, we insert our static subdomains for for concurrencey (so we don't worry about subdomains during development . links for 2008-03-21 Bloggitation says (on March 21st, 2008 at 12:21 am [222] )

 

[] Serving JavaScript Fast (tags: javascript ajax web2.0 tuning sysadmin) [] Philippe says (on March 21st, 2008 at 2:34 pm [223] )

 

How to generate a file with subversion revision numbers for each files in php ?

 

"At the point when we go to build our site for deployment, we simply check the revision numbers of all of our resource files and write them to a static configuration file." Cal Henderson says (on March 21st, 2008 at 7:39 pm [224] )

 

Philippe:

 

you can use svn's ls command to get the latest revision number for a file, for example:

 

$ /usr/bin/svn ls -v file:///var/svn/flickr-test/trunk/index.gne 45324 mygrant 9894 Jan 23 19:13 index.gne Eric Martindale says (on April 2nd, 2008 at 4:41 pm [225] )

 

Great work! I'll have to see what I can do to implement some of these methods in the AJAX Chat [226] that I've recently taken over

 

now if only I could get sockets working correctly. ;] Adriaan Nel says (on April 2nd, 2008 at 5:44 pm [227] )

 

I've gotta say, I've never had a problem with sites becoming so busy that they are served slowly to the end user, even large dynamic pages, and I'm also talking about relatively high usage sites (more than 2 mil page views per month).

 

I always try to optimize everything, but haven't implimented anything this far reaching yetmaybe I'll give it a try and see if it really helps.

 

Thanks for the article though. Derrick says (on April 2nd, 2008 at 6:01 pm [228] )

 

It'd be much cooler if part of your deployment process was the merging of the js files, vs taking a script hit each time a page is requested. Otto says (on April 2nd, 2008 at 8:57 pm [229] )

 

The site worked okay for me. The content is large, so I'll summarize it: 1. Combining small JS files into one big one is not always a good thing. Keep them separate and lean, but low in number. Use PHP to merge them on the fly where needed and where it make sense to do so. 2. CSS: Same thing. 3. Compression. Use it. mod_deflate and or mod_gzip are good, but precompressing the files when you deploy is better. Insert way to make mod_gzip work with precompressed gz files here. Insert the trick to make mod_gzip compress and cache on the fly here. 4. Compression doesn't work with some old as hell browsers (seriously, Netscape 4? You're worried about Netscape 4? Oh, the article was written in 2006, I get it), so using javascript and/or CSS compressors as part of your deployment process can be helpful (ugh). 5. Send good cache and expires headers. Put some thought into this, as it helps more than anything else when done right. 6. Smart use of rewrites can make things easier to code, and by changing filenames this way, you can force cache busting. 7. Combine techniques.

 

In short, it's a useful primer for those developers who didn't know much about web development already. isao says (on April 3rd, 2008 at 1:10 am [230] )

 

nice article. the techniques apply to other content types besides javascript of course. realted: http://developer.yahoo.com/performance/ Jeremy says (on April 3rd, 2008 at 1:41 am [231] )

 

Very nice article. I've already sent it to my team for review and will go over it with them tomorrow.

 

I'd be very interested to see some benchmarks that detail the number of JS files on the x-axis vs. load time on the y-axis. As the number of JS files increased you could assume the size of each file decreased. For example, point 1 on the x-axis would be one (1) 100k file. Point 2 would be two (2) 50k files. Point 3 would be three (3) 33k files, etc.

 

Please let me know if someone has those benchmarks somewhere.

 

On a separate note, I have experienced IE 6 and 7 caching pages with the same query string but the easiest workaround I've come across is adding a random query string value: &rand=x where x is the current timestamp. The Yahoo User Interface has the ability to use this technique with their connection manager and it works like a champ. I've never had a problem with Firefox caching URLs with query strings. Rick Torres says (on April 3rd, 2008 at 7:59 am [232] )

 

Great ideas ! I hope to speed up my page by breaking the .js files in modules that are served on specific pages only.

 

This resource was a great help to me ! TechMount Archive Daily Friction #325 says (on April 3rd, 2008 at 8:58 am [233] )

 

[] Serving JavaScript Fast - With our so-called "Web 2.0 applications and their rich content and interaction, we expect our applications to increasingly make use of CSS and JavaScript. To make sure these applications are nice and snappy to use, we need to optimize the size and nature of content required to render the page, making sure we’re delivering the optimum experience. [] Serving JavaScript Fast says (on April 3rd, 2008 at 10:33 am [234] )

 

[] read more | digg story Explore posts in the same categories: Uncategorized [] jive says (on April 3rd, 2008 at 4:17 pm [235] )

 

Yahoo recommends you put your JavaScript at the bottom of the page before the closing body tag. Serving JavaScript Fast | White Sands Digital says (on April 6th, 2008 at 12:43 pm [236] )

 

[] The next generation of web apps make heavy use of JavaScript and CSS. We ’ll show you how to make those apps responsive and quick.read more | digg story Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages. [] Improving Performance by Combining all Scripts and CSS | ~/my-other-beans says (on April 9th, 2008 at 1:51 pm [237] )

 

[] Although they do not provide the source code for the ASP.NET control, they do point to an old article on Vitamin, Serving JavaScript Fast, that served as their inspiration. []

 

Acronyms says (on April 10th, 2008 at 7:47 am [238] )

 

Bookmarked. Thanks a lot. BTW having a brief summary of principles would be really good to have. Serving JavaScript Fast Know Things says (on April 11th, 2008 at 7:39 am [239] )

 

[] read more | digg story []

 

LEAVE A REPLY

 

Name (required)

 

Mail (will not be published) (required)

 

Website

 

Basic HTML (, , , etc.) is allowed in your comments. Please be respectful and keep your comments on-topic. If we think you're being offensive for no reason, we'll delete your comment.

 

Anti-spam question: What is 7 + 9? (required)

 

Comments RSS

 

FEATURE CATEGORIES

 

AJAX [240] (5) Biz [241] (34) Blogs [242] (3) CSS [243] (15) Design [244] (38) Dev [245] (16) DOM [246] (2) JavaScript [247] (6) Rails [248] (3) Ruby [249] (1) Web Apps [250] (28)

 

Ads via The Deck [251]

 

FAVOURITE FEATURES

 

How C.R.A.P is Your Site Design? [252] By Mike Rundle [253] (288 comments) Stop Hacking, or be Stopped [254] By Dave Shea [255] (233 comments) Creating Sexy Stylesheets [256] By Jina Bolton [257] (197 comments) Serving JavaScript Fast [258] By Cal Henderson [259] (196 comments) HTML Emails - Taming the Beast [260] By David Greiner [261] (194 comments)

 

SUBSCRIBE

 

[262] Please enter your email address:

 

SEARCH

 

Keywords Section Everything Features Training Reviews Interviews

 

Copyright (c) 2008 Carsonified Valid XHTML [264] & CSS [265] Vitamin is brought to you by Carsonified [266], creators of DropSend [267], FOWA [268], FOWD [269] and FOM [270]

 

 

 

Google
 


All content mirrored on this site is generated from the open-source browser, Lynx. Ads are included simply to pay for our bandwidth in supplying this free service. All content is copyright the original owner (see mirror of: in the header).