i have an issue i don't really know how to control.
I have a server where i host a bunch of JS files that i let external websites to import.
My issue is that every time that a user changes page on the same website, he's asking again my server for the same JS file, therefore my outgoing bandwidth is exponentially increasing.
I do not have control over apache on the websites that ask for my JS files.
Is there a way i can have people import the JS file once per session, caching it on their browser for a certain amount of time?
In other cases the websites incorporates a .js file (hosted on my server) and that JS file, once loaded, starts many ajax calls (getScripts) in order to import other JS files himself.
I'm looking for a solution for caching those files having a way to control if the script needs to ask for them again or not, since this is consuming a lot of bandwidth i'd like to spare.
thanks!
in fact there was an answer to this, at least regarding the dynamically loaded JS files.
You can set the parameter "cache: true" in the ajax calls from jQuery. This way the script will just be taken from cache if present.
Technically this solved my issue.
Related
I am compressing all of my files on the go, so it's easier to update rather than having to decompress. I have around 10 JS files, in total around 2,000 lines maybe more, would it be better to put them all in one file and compress it, would it speed up my website, or should I just leave it in individual files, and compress each?
I'm assuming this is for web development.
If all of your scripts were created by you, and you suspect each script will be needed for every page on your site, you should concat / compress them. The first load will take longer, but the scripts will be cached.
If all of your scripts were authored by you, but each page does not necessarily need all 10 of your scripts, you should consider lazy loading them on demand.
If any of those scripts were not authored by you and can be found on a CDN (like jQuery), then link the scripts to a CDN, as there is a chance users will already have them cached. For the remaining scripts, decide if you should lazy load or concat / compress them all.
What you shouldn't do, however, is load all 10 of your scripts individually on each page. That would just have the user's browser send more requests than needed.
It's all about trade-offs, and there isn't a 100% correct answer. Good luck :)
--edit--
You said "on the go". If the content of your scripts change, then you wouldn't want them to be cached. In that case, lazy-loading would probably be the answer.
--edit 2--
If you haven't already, you should really take a look at using Grunt to concat and minify your js files during development. If you decide to go that route, take a look at grunt-contrib-watch.
It is often a good idea to keep the number of files the browser needs to request to a minimum.
The browser may have to open one connection per HTTP request, but if you put all your JavaScript code in one big file it will only have to do one request and thus only one connection needs to be opened to fetch your js code.
It depends on how much of that 2000 lines you are using for different pages. If the file is like a library of which most is used in your distinct pages, then it might actually make little to no difference in terms of loading speed. But if only a part of that file is being used in each page, I would assume separating would be smart as less will be needed to load per page.
I have a web application that is currently split into like 40+ javascript files. When I run the application some subset of those files need to be downloaded by the browser. Obviously, given that browsers use ~6 threads to download files, this is not the optimal solution. One optimization idea that come to my mind was to embed all those javascript files (except external ones) inside the served .aspx page. So that the browser just gets one big html file and does not need to make any round trips to the server. The html page alone may contain user specific data that will be different on every request. The scripts, however, are not changing between requests. In typical use case the page (complete with scripts) has 180KB (scripts not minified) or 130KB (minified).
Now the question: does this approach have any drawbacks performance wise (network, browsers' javascript engines)? Do you know of any big applications doing something like that? Note that I am not interested in arguments about eg. maintainability as the individual scripts will still be available as separate files during development. Same question applies to css files (even though this is less of an issue in my app).
One bit of information that may be important here: the application is one big multipage form that does not require postbacks to go between the pages, validate form, submit the form, etc. However, the application in which it is embedded may have multiple such forms.
In general, it is a very good idea to concatenate javascript and css files together. I'm just not so sure about "your concept". My biggest concern and question here would be, can that .aspx file change potentially in any way through (dynamic) code ?
That would make in impossible for the browser to cache the file, which would be a horrible scenario.
The great thing about concatenating files is, that we have one big downstream (which still is a lot faster then downloading with several single requests and HTTP overhead) and the browser can cache this file afterwards.
There are some great build-tools and scripts available, Apache ANT is one I can really suggest. You should have a look on the HTML5 Boilerplate where they make usage of ANT very frequently.
I have a QWebView in my app which renders a html page stored in the app as a Qresource. This page, however requires meaty external Javascript libraries such as MathJax, which I would want to include as a resource due to its size.
My problem is that it seems that QtWebkit does not cache these files as a regular browser would do, and every time I refresh the widget it downloads MathJax afresh.
So my question is: is there any way to cache these libraries after first time they are downloaded, without having resorting to shipping it with the app as resource?
You should try if a simple QtNetwork-based download honor the cache setting or not. Also, see if the settings (QWebSettings) are set properly.
In all case, you should be able to inject a custom QNetworkAccessManager that handles the caching of your custom JS library. See http://ariya.blogspot.com/2010/05/qnetworkaccessmanager-tracenet-speed.html and http://ariya.blogspot.com/2010/06/proxy-server-with-filtering-feature.html as examples and follow it up from there.
Could you post some source code? Once downloaded that data will stay in the /tmp/ folder for some time. You could likely use the data in the temp folder, my guess is you are not enforcing that policy.
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.
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.
Generally best practices related to javascript for speeding up website loads are:
Minify all javascript and put all of it into a single file (make as much of your javascript external as possible).
Put javascript at the bottom of the document.
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>)
Configure your web server to gzip all text files.
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).
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.
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
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.
How to determine if a javascript was already loaded by other html file? I want to reduce the redundant loading of the javascript files to decrease the loading time of my webpages.
If your web server is providing correct caching headers this shouldn't be necessary, the browser will cache the javascript file across multiple requests.
You might want to check out the YDN page Best Practices for Speeding Up Your Web Site
If you want to prevent the files from being downloaded twice then this will be automatic provided they are set to be cacheable (most webservers should set these headers sensibly by default).
If you want to make sure that the include tag happens only once when including files in a dynamic language then you will need some sort of manager. ASP.NET provides a scriptmanager class that does this (among other things). I cannot speak for other languages and frameworks
As Rory says the second request will probably be cached, and noting that this is a bit of a design failure if it can happen, you can understand that the cached file is still going to execute with negative effect.
This is horrible, but you could wrap your JS script like this:
if (!document.foo)
{
//your script here
document.foo = true;
}