Speed Up Your Javascript Load Time

[转载] http://betterexplained.com/articles/speed-up-your-javascript-load-time/


Part 1

Javascript is becoming increasingly popular on websites, from loading dynamic data via AJAX to adding special effects to your page.

Unfortunately, these features come at a price: you must often rely on heavy Javascript libraries that can add dozens or even hundreds of kilobytes to your page.

Users hate waiting, so here are a few techniques you can use to trim down your sites.


Find The Flab

Like any optimization technique, it helps to measure and figure out what parts are taking the longest. You might find that your images and HTML outweigh your scripts. Here’s a few ways to investigate:

1. The Firefox web-developer toolbar lets you see a breakdown of file sizes for a page (Right Click > Web Developer > Information > View Document Size). Look at the breakdown and see what is eating the majority if your bandwidth, and which files:

yahoo-size_1.PNG

2. The Firebug Plugin also shows a breakdown of files - just go to the “Net” tab. You can also filter by file type:

yahoo_firebug.png

3. OctaGate SiteTimer gives a clean, online chart of how long each file takes to download:

yahoo_octagate.png

Disgusted by the bloat? Decided your javascript needs to go? Let’s do it.


Compress Your Javascript

First, you can try to make the javascript file smaller itself. There are lots of utilities to “crunch” your files by removing whitespace and comments.

You can do this, but these tools can be finnicky and may make unwanted changes if your code isn’t formatted properly. Here’s what you can do:

1. Run JSL int (online or downloadable version ) to analyze your code and make sure it is well-formatted.

2. Use Rhino to compress your javascript. There are some online packers , but Rhino actually analyzes your source code so it has a low chance of changing it as it compresses, and it is scriptable.

Install Rhino (it requires Java), then run it from the command-line:


This compresses myfile.js and spits it out into myfile.js.packed. Rhino will remove spaces, comments and shorten variable names where appropriate. The “2>&1″ part means “redirect standard error to the same location as the output”, so you’ll see any error messages inside the packed file itself (cool, eh? Learn more here. ).

Using Rhino, I pack the original javascript and deploy the packed version to my website.


Debugging Compressed Javascript

Debugging compressed Javascript can be really difficult because the variables are renamed. I suggest creating a “debug” version of your page that references the original files. Once you test it and get the page working, pack it, test the packed version, and then deploy.

If you have a unit testing framework like jsunit , it shouldn’t be hard to test the packed version.


Eliminating Tedium

Because typing these commands over and over can be tedious, you’ll probably want to create a script to run the packing commands . This .bat file will compress every .js file and create .js.packed:


Of course, you can use a better language like perl or bash to make this suit your needs.


Optimize Javascript Placement

Place your javascript at the end of your HTML file if possible. Notice how Google analytics and other stat tracking software wants to be right before the closing </body> tag.

This allows the majority of page content (like images, tables, text) to be loaded and rendered first. The user sees content loading, so the page looks responsive. At this point, the heavy javascripts can begin loading near the end.

I used to have all my javascript crammed into the <head> section, but this was unnecessary. Only core files that are absolutely needed in the beginning of the page load should be there. The rest, like cool menu effects, transitions, etc. can be loaded later. You want the page to appear responsive (i.e., something is loading) up front.


Load Javascript On-Demand

An AJAX pattern is to load javascript dynamically , or when the user runs a feature that requires your script. You can load an arbitrary javascript file from any domain using the following import function :


The function $import('http://example.com/myfile.js') will add an element to the head of your document, just like including the file directly. The $importNoCache version adds a timestamp to the request to force your browser to get a new copy.

To test whether a file has fully loaded, you can do something like


There is an AJAX version as well but I prefer this one because it is simpler and works for files in any domain.


Delay Your Javascript

Rather than loading your javascript on-demand (which can cause a noticeable gap), load your script in the background, after a delay . Use something like


This will call loadExtraFiles() after 5 seconds, which should load the files you need (using $import ). You can even have a function at the end of these imported files that does whatever initialization is needed (or calls an existing function to do the initialization).

The benefit of this is that you still get a fast initial page load, and users don’t have a pause when they want to use advanced features.

In the case of InstaCalc , there are heavy charting libraries that aren’t used that often. I’m currently testing a method to delay chart loading by a few seconds while the core functionality remains available from the beginning.

You may need to refactor your code to deal with delayed loading of components. Some ideas:

  • Use SetTimeout to poll the loading status periodically (check for the existence of functions/variables defined in the included script)
  • Call a function at the end of your included script to tell the main program it has been loaded


Cache Your Files

Another approach is to explicitly set the browser’s cache expiration. In order to do this, you’ll need access to PHP or Apache’s .htaccess so you can send back certain cache headers (read more on caching ).

Rename myfile.js to myfile.js.php and add the following lines to the top:


In this case, the cache will expire in (60 * 60 * 24 * 3) seconds or 3 days . Be careful with using this for your own files, especially if they are under development. I’d suggest caching library files that you won’t change often.

If you accidentally cache something for too long, you can use the $importNoCache trick to add a datestamp like “myfile.js?123456″ to your request (which is ignored). Because the filename is different, the browser will request a new version.

Setting the browser cache doesn’t speed up the initial download, but can help if your site references the same files on multiple pages, or for repeat visitors.


Combine Your Files

A great method I initially forgot is merging several javascript files into one. Your browser can only have so many connections to a website open at a time — given the overhead to set up each connection, it makes sense to combine several small scripts into a larger one.

But you don’t have to combine files manually! Use a script to merge the files — check out part 2 for an example script to do this. Giant files are difficult to edit - it’s nice to break your library into smaller components that can be combined later, just like you break up a C program into smaller modules.


Should I Gzip It?

You probably should. I originally said no, because some older browsers have problems with compressed content.

But the web is moving forward. Major sites like Google and Yahoo use it, and the problems in the older browsers aren’t widespread.

The benefits of compression, often a 75% or more reduction in file size, are too good to ignore: optimize your site with HTTP compression.


All done? Keep learning.

Once you’ve performed the techniques above, recheck your page size using the tools above to see the before-and-after difference.

I’m not an expert on these methods — I’m learning as I go. Here are some additional references to dive in deeper:

Keep your scripts lean, and read part 2 for some working examples.


Part 2: Downloadable Examples!

I’m happy people are finding the article on javascript optimization useful. But I made a giant, horrible mistake. A mistake that befalls many tutorials.

I didn’t include actual, working examples for you to play with. You can talk all you want, but until you’ve got some code, it’s just theory and listless sighs. And without seeing the code walk (or run! Get it?), it’s hard to believe that it really works. So here’s some live, working examples to show these techniques in action:

The examples are free and in the public domain. However, if you find it useful I’d appreciate you sharing it with friends or dropping me a note . I like knowing what explanation styles work so I can do more of it in the future.

And now, the guided tour of what you’ll see in the zip file.


Eliminate Tedium: Use Scripts

Automate, automate, automate! I’ve created a set of batch files (and .sh files for you Linux/UNIX gurus) to get you started:

  • makeall.bat : Runs the commands below
  • make_libraries.bat : Combines *.js into “allfiles.lib.js”, and combines files prefixed with “example” into “example.lib.js”.
  • pack_js.bat : Compresses *.js and creates *.js.packed
  • add_cache_header.bat : Inserts the PHP caching header into the .js.packed files, creating js.packed.php
  • cleanup.bat : Removes generated files, leaving you with your original .js files.

These are templates - modify them to suit your own needs. If you find yourself typing a command again and again, throw it into a script.


Compressing Javascript

I’ve included custom_rhino.jar which does the compression (more info ).

There are a few javascript files for demo purposes. The first is example_compressed.js , which has extremely long variable names in various scopes (local and global). Take a look at this sucker, it’s ripe to get crunched by Rhino:


A typical “javascript compressor” will simply remove extra spaces and comments, which doesn’t help much. Rhino actually analyzes your code: when it sees global variables, it knows the name shouldn’t be changed since other scripts may reference them.

But local variables are another story. Since locals are only referenced inside of their function , they are ripe for squashing. This is your javascript on Rhino:


Any questions?

Rhino trampled the variable names and replaced them with the shortest identifiers it could find: _1, _2, etc. This saves a lot of space, and has the side-effect of partially obfuscating your code (if you are looking for that sort of thing).


Dynamic Import and Delayed Loading

Now here’s the fun stuff: example_imported.js and example_delayed.js don’t do anything special, except call a logging function that shows when they were loaded.

Check out sample.html


Take a look at the result :

sample_html.png

Notice how $import acts immediately, and the delayed load happens 5 seconds later. All the scripts call the log function, but it could be any callback, like registerLoadEvent() or displayHiddenFeature() . Leave that for your imagination.


Creating Library Files

It can also be helpful to combine smaller files into a larger one, especially if they don’t change often. This reduces the number of requests the browser makes and you don’t suffer the overhead for each item.

Downloading one 10k script is faster than ten 1k ones - browsers can only have a certain number of connections open at a time. Once you’ve got the connection going, you may as well cram a larger file down.

The UNIX “cat” (or Windows “type”) command is perfect for this. If you set a filter (example*.js) you can combine files with the same prefix into a library:


And since the library ends in .js, it will get packed along with the other .js files in our packing script.


Adding PHP Cache Headers

The last step is to add the cache headers to the files. There is a general “set_cache_header.php” file that is combined with the packed javascript (.js.packed) to create the js.packed.php files. Assuming your server is configured to serve PHP, this will set the caching headers for 3 days (change this to any number you like ).


Always Keep learning

We’re never done learning — I’d love to see what other tricks you use to speed up your javascript or automate the “build” process.

Remember that there are all sorts of interesting callbacks you can do. The scripts, once loaded, can call functions to display previously hidden features in the page: as scripts are loaded, menu items/images/text could appear. Or, you can just have one master script that $imports the others, so you don’t need to monkey with your HTML file if you add a new javascript file (some Javascript libraries behave this way). The possibilities go on: use some, all, or none of these techniques. Experiment and learn what works for you.

Happy hacking.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值