views:

245

answers:

6

I have a couple of questions that are somewhat related so I'm posting them all on a single question on SO...

Question 1:

I'm currently doing this Facebook application where I'm using jQuery UI Tabs, there's only 4 where 2 of them are loaded through Ajax. The main page is index.html, this is where the tabs code is placed and for the 2 tabs loaded through Ajax, I have two different files, tab1.html and tab2.html.

Currently, the jQuery tabs initialization and Facebook JavaScript initialization is done on index.html. Both tab1.html and tab2.html have JavaScript code that belongs to those pages. For instance, tab2.html has a form and there's some JS (with jQuery) code to validate the form, this code is irrelevant to tab1.html as the JS code on tab1.html is irrelevant to tab2.html.

My question is, should I keep doing this or maybe aggregate all the JS/jQuery code in index.html, tab1.html and tab2.html in a single global.js file and then include it in index.html?

I though of doing this but there will be irrelevant code loaded if the user never opens tab1 or tab2. The benefit of using a single global.js file is that I could pack/minify the file, which I couldn't do if I included each code block in each respective tabX.html file.

Question 2:

As I'm using jQuery, I'm also using lots of plugins (actually only 3 for now, but that number can grow). Some of them provide a minified JS and I use those when available, when they are not, I use the normal versions of course.

There's also the requests problem. If I have lots of plugins, say 10, it will be 10 requests for those plugins. And there is also the fact that some plugins are used in tab1.html but not on tab2.html and vice-verse.

How should I load all the plugins in a minified/packed version on a single web request? Should I do that manually before publishing my app (packing and merging them into a single file) or could I use the PHP version of Dean Edwards's Packer and pack/merge all plugins on the fly? Would this be a good approach?

Question 3:

If the answer on Q1 was something like "merge all code in a single global.js file", should I include the global.js file in the packing/merging script I described above on Q2?

Doing this would simplify everything. I could have my development environment properly organized with all .js files, for the plugins and the global.js in the appropriate folders without bothering with anything else. The packing/merging should take care of the rest (pull the files from the respective folders, send the respective JS headers and output one single packed .js file).

The one thing that's confusing me the most is that not all plugins are used for every tab, not all code is for every tab too. Still, a chunk of the code is global to every tab and the index. This also simplifies everything as: a) I don't have to worry to add the needed code to each tabX.html file and can I simply look at them as HTML templates and nothing else; b) I don't have to be bothered in including the necessary plugins where I need them as I'm currently using $.getScript() from jQuery to load the plugins I need when and only when I need them, but I'm not sure this is a good approach and the code feels dirty and ugly like this.

A: 

Question 1:

The best practice would be to place all js files in a single "global" file. This minimizes your HTTP Requests. Let's say you have 5 plug-ins, this would me you need to do 5 request, wherein if you combine them as one, you only need to request it once. This might be a little bit heavy on the first load, but the next time around this file will be cached by the browser, so..no worries about the size. HOWEVER, be careful about the sequence of the scripts when combining it. (I.E. : JQuery script should be placed first on the js file before JQuery UI's)

http://articles.sitepoint.com/article/web-site-optimization-steps/4

http://code.google.com/speed/page-speed/docs/rtt.html

Question 2: You can do it manually or automatically.Dean Edward's Packer is a good choice. If you're using ASP.NET, you can check MB Compression Handler, if you're using APACHE with PHP perhaps you can change the configuration of your htaccess to gzip it

Question 3: It'd be better if you pack the "global" javascript file as well. This could save up bandwidth and save more time to load. You got the point, combining all the js files you need for the site will save you time from including individual scripts.

xar
You are misunderstanding all my questions... Q1 doesn't have anything to do with multiple requests as there isn't any .js files. Q2 has nothing to do with compression but packing. Actually I never talked about compression, that's a completely different subject that I'm not interested in discussing here.
Nazgulled
+1  A: 

Generally best practices related to javascript for speeding up website loads are:

  1. Minify all javascript and put all of it into a single file (make as much of your javascript external as possible).
  2. Put javascript at the bottom of the document.
  3. Force web server to assign expiration date in the future and use a timestamped query string to invalidate old versions of javascript files, this will prevent unnecessary requests for your javascript if it has not changed. (ie: in httpd.conf ExpiresByType application/x-javascript "access plus 1 year", in your document: <script type="text/javascript" src="/allmy.js?v=1285877202"></script>)
  4. Configure your web server to gzip all text files.
vls
With all due respect, I didn't ask for "general best practices", I made specific questions for my own issues.
Nazgulled
@Nazgulled: To try answering your question more specifically -- you have to weigh the complexity, performance and potential bandwidth savings of leaving embedded js fragments vs. combining into external file depending on specifics of your application. In your case, moving javascript out into external file will likely improve performance, reduce complexity and with points in my post implemented might even reduce bandwidth. Unless you generate custom js in your tabs, then you can't move that particular js out.
vls
That still doesn't answer some doubts (posted in the question) I still have...
Nazgulled
+1  A: 

The main reason why you should keep too much javascript away from tab pages is because it will kill user experience. When a user clicks on a tab for the first time it will grab all the components needed on the fly which makes it kinda sluggish.

You're question is only semi-specific as we don't know a lot of things about your site like exact file sizes, how the modules are really used.

The general idea would be to find balance between modularity and speed.

When you're combining modules together these are the general ideas you should consider:

  • how often does this module change?
  • how often is this module used?
  • how big is this module (filesize)?

Then put the most used, stable codebase and merge it into one. Then you should include the rest site specific functionality on the tab pages.

Also, make sure to load javascript asynchronously as it won't block rendering of the page (and tabs).

galambalazs
Everyone seems to avoid Q2/Q3 though... In spite of being the first one, it's the least important. I need better answers to Q2/Q3 :(
Nazgulled
if you read carefully i answered your questions: I dont advise you to make one big file because if any bit of it changes, the user has to download it again. This is why I wrote you should group files by how often they change. And make a stable codebase that barely changes, separated from the codebase that is mutating frequently.
galambalazs
That's too much work just thinking about it and I don't think the benefits of doing so are worth it.
Nazgulled
And so the tale of lazy programmers and unhappy users begins...
galambalazs
It's not about being lazy, it's about not being worth it for this specific website... I'm not developing the next Facebook, it's just a simple app.
Nazgulled
+1  A: 

Another combined answer:

if adding all the JS together in packed/minifed version generates no more than 30k of file size you're better off combining it. A single extra connection for a file (assuming it's not cached) is worth 10-20k of extra JS download. This has to do with browsers opening and closing connections vs streaming extra 20k on an established connection. The threshold also depends on your user distribution. If you have a lot of dial-up or low bandwidth users your threshold will be smaller.

I typically recommend combining and loading as 1 file unless the library is very obscure and requires a very edge case for it to be triggered on a page. Ex: Hover triggers functionality Y but it's on a feedback widget that gets less than 1% of traffic- don't bother combining.

Minifying and Packing is a little overrated these days. With the vast majority of browsers supporting gZip the amount of data consolidation gZip provides of the file over the wire during browser transmission has virtually the same effect as min/pack. However, there is a small cost on the browser to unpack it. Having said that, it's still good practice to min/pack the code since not all browsers support it, you may not want the file to be gZip enabled, etc.

I've used online packers against 3rd party module and it works fairly well. However, there are times when it can cause an issue so make sure to test your manually packed version before deploying.

Alternate:

If you feel that your users will rest on your index page for longer than 10 seconds you could pre-load the additional libraries separately using Js Loader Prototype pattern.

nopuck4you
+2  A: 

Question 1:

Pack them all into a single .js file. This will make maintenance easier, and the tiny bit of overhead for the user loading a little js they they potentially may not use does not matter. I would also let Google load the jQuery library for you and then have all of your js code in a single separate file.

Question 2:

As these plugins don't really change I would manually combine them. Closure Compiler is good at this. When minifying use the highest setting that does not give any warnings.

Question 3:

Yes you will want to minify the global.js

When the browser downloads the global.js it's cached for an amount of time. Thus when you call the entire global.js again on a different page, its not re-downloaded it looks at your local copy first. So you do a little bit more work at first on the initial download, but from then on, it should be quicker.

corymathews
One last question though, should I have 2 files for the global JS code and the plugins code (global.js/plugins.js) or just one single global file for all my JS code and plugins? Also, Closure Compiler looks nice but it forces me to use it every time I add/remove plugins or update my own JS code, which is kinda boring. Maybe Minify (http://code.google.com/p/minify/) is a better option for that?
Nazgulled
It comes down to personal preference. I usually split them because the plugins will rarely change, so I rather them be elsewhere. On the flip side if I only have 1 or 2 plugins I will add them all in 1.
corymathews
I have not personally used minify, but it looks like it just automates doing the updates by hand. So that would be up to you as well.
corymathews
+1  A: 

Steve Souder's Even Faster Websites is a book you should look into.

Firstly one experience slowdowns because whenever an external script is linked the browser waits for the script to download, parse and then execute. After this only it regains processing rest of the request. So to avoid such slow downs one can look at parallely downloading the scripts. Few techniques are Ajax the scripts if the scripts are in the same domain or use Script Dom element or Script in iframe if the scripts are on external domains

Q1 : For me modularising all the content is a better option with respect to further development if the page content has to be changed constantly. Responsiveness is very important for the end user. A small global.js will help in getting the app up and running.Parallely one can download the tabX.html.

Q2: As the jquery plugins rarely change. The plugins for the tabX.html pages can be downloaded parallely and locally cached so when the tabX.html is loaded the required plugins need not be fetched. SO all the plugins required by the main page should be in one single file and the ones used by the tabX.html's should be in different files.

Q3 : its a personal choice here. Do you want it to be developer friendly or user friendly. I bank on user friendliness. Making responsive and efficient apps is our job !!!. All the advantages of packing everything into a singe files is you will have ease in development. Well ugly code begets beautiful apps :). Users are speed-aholics. For eg. when google changed its 10 results per page to 20 they saw a considerable drop in search queries. So my opinion is not to pack all of them into one and load each parallely

some of the techniques and relevant links on testing each:

XHR eval /ajax : http://stevesouders.com/cuzillion/?ex=10009

XHR Injection : http://stevesouders.com/cuzillion/?ex=10015

Script in Iframe : http://stevesouders.com/cuzillion/?ex=10012

Script DOM element : http://stevesouders.com/cuzillion/?ex=10010

jknair