AJAX Application Single or Multiple JavaScript Files - javascript

This is a best practice type of question. I am developing a complete AJAX application. The user navigates to the main page of the application and everything from there on out is loaded via AJAX into the content section of the main page. Is it better to take all the javascript files I have and merge them into one file that is loaded on the main page or to split them up into just what is needed for each page that is loaded?
Putting it all in one file obviously has the benefit that only one HTTP request is made to load the javascript needed for the site and any request for a page there after will only need to fetch the HTML. But, this requires that every event that is wired up (using jQuery) be attached to the document using the live or on function. So everything will look like:
$(document).on('click', '#SomeButton', function () { });
Doing it this way will cause there to be many hundreds and possibly over a thousand events being tied to a single element, the document.
Putting them in separate files requires multiple HTTP requests to be made to load the various pages of the site but limits the number of events that are attached to the document.
Any thoughts on what is best here?

I would vote for separate js files for each page for bigger projects specially if your project is using any js library like jQuery and its plugins like grid plugin etc. In case you have a big single javascript file your first page will load slowly obviously giving your user a bad first impression. What we do is that we create separate js files for each page specially when there are ajax calls to load data for the pages. Plus there are separate files for each pluggable component like custome drop down or date counter etc. This way its easy to manage the code and customize it later.
Before deploying the app we can merge related files and create single file for a single page. For example if a page called editProfile.php uses a data picker, a jquery validation plugin and custom js to load user data, we can combine them in a single file so that only file will be loaded for a single page.
So I would vote for separate files for each page and applying optimizations before deploying.

Honnestly i'm not really an expert in this domain but this is my piece of advice on this subject on a production environment.
I would use CDNs for libraries (like jquery). They offer maximum cacheability, and there is a very big chance it is already cached in your client's browsers from visiting other websites. This saves some requests already.
Group and minify your common javascript code, like plugins, utilities, things used throughout your site. It will be requested once for all and will then be available.
Have a separate, minified, script file for each "page" you load dynamically that you will load along with your content.
Loading script for content pages:
Using the .load() method from jquery to load fragments of pages will unfortunately remove any <script> tag present in the fragment. As noted in the jquery load() method, this is to avoid "Permission denied" in IE.
What you can do is to have a <script id="contentScript"></script> tag in your base page and load the script along with the content by replacing the src.
I don't know if it is a good practice but it makes sense to me :-)

Related

Is it better to split JavaScript into multiple files, or have it all in one file?

Assume a website running on a Linux server. There are three pages. One page has an AJAX call, one has a JavaScript-generated calendar, and the third has a lightbox image gallery. They also share some common JavaScript functions.
There are two ways I've handled this kind of setup before. Method 1: create four .js files. One with the common functions (loaded on every page), and three more with each distinct page function. Each page loads two scripts: the common script, and the specific script for that page's content. The page makes one extra HTTP request, but doesn't load any extraneous script.
Method 2: Put everything in a single .js file, and each page loads that one file. Only one HTTP request, but each loads a lot of extraneous JavaScript (for example, the Calendar page will also be loading the script for the Gallery page AND the AJAX call page).
Assuming that proper function naming etc. is not an issue, so we don't need to be concerned about function name overlapping etc, which scenario is best for site load time and overall performance? An extra HTTP request per page, or lots of extraneous JavaScript per page?
It depends on the size of your Javascript and the data connection of the user, as well as the (non-)use of technologies such as HTTP2.
In general the answer is that combining separate Javascript files into a single file per page is better for performance. There's nothing to say you couldn't do this separately for each of your pages, meaning you'd have a single Javascript file with the page-specific functions, as well as the common functions you've described. You can do that manually, or use a tool like gulp to perform the task automatically.
I would serve them in one file as one HTTP request is preferable even to loading lots of JS. If it is a huge JS file, consider minification.
I would do one file, and make sure your server response headers allow client-side caching. Then there is only one HTTP request for the JS file, even if they visit all the pages on your site.

Block JS from loading on certain domains

I have a web service that works through giving users javascript to embed in their code. Users can also place that code on other sites to make it work there. However I also need to allow users to create a blacklist of sites that the JS should not function on. For example, a competitor or an inappropriate site.
Is there a way to check where our JS files are being loaded from, and block loading or break functionality on a per account basis?
Edit: The javascript loads an iframe on the site, so another solution would be to somehow block certain domains from loading an iframe from our server, or serve different content to that iframe
Edit 2: We're also trying to avoid doing this from with the JS because it could be downloaded and modified to get pass the block
Inspecting the url of the page
Yes, the javascript file, when it starts executing, can inspect window.url and see if the url of the main document is ok.
To see where the script was loaded from
It can also go through the dom, looking for the script node which brought in the javascript file itself and see from where the JS was loaded.
However
Anyone can load the javascript into a text editor, then change it to eliminate the tests, then host the modified JS on their own server. Obfuscating or minimizing the JS can slow someone down but obscurity is not security.
One thing you could do is have the javascript load another javascript file. That you serve from the server at a given url. The trick here is that that url will not go to a file but to a server end point that will return a javascript file. The you have that endpoint check for the routes for that user and decide if it will return the javascript you want to work or an error javascript of some kind.
This blog shows how to do it in php.dynamic-javascript-with-php

Javascript file modifying an html file that it is not called from? Jquery Selectors

Is its possible to have a javascript file that is aware of two different HTML files? And how would I do this?
I would like to be able to have two pages. index.html and pictures.html. I have an index.js that changes the display properties of index.html (it puts data based on people into tables and makes it look nice). I would like this current index.js file also to be able to edit the pictures.html file and change information there. index.html would link to pictures.html to display pictures of a person (based on the persons name I have them saved smith1.jpg, smith2.jpg, reagan2.jpg, ect). Is there anyway that this javascript file could get DOM elements based on their id or class of the second file (pictures.html) even though it "lives in" index.html? When i say lives in it is called at the top of the index.html page.
thanks
A script can access elements on another page if it was loaded in some way of connection.
For example, if you make a popup using var popup = window.open(), the return value will contain a reference to the opened popup and this allows access to elements within the popup. E.g. popup.document.getElementById('something'). Pages loaded within frames, iframes and such have similar ways of access.
So yes, if your page loads the second page its script can work there as well. I suggest avoiding this beyond opening and closing popups from a script though; a script should stay inside the box of its page and if it needs to do larger operations on another page, that usually means that you need to change your code architecture a bit.
You'll need to explore server-side programming to accomplish your goal.
http://en.wikipedia.org/wiki/Server-side_scripting
...Or you could write a client-side application in which "pages" are separate views of one actual page or are generated from backing data structures. If you want persistance of what is created/edited, you'll still need server-side programming.
You can use the html5 (group of technologies) postmessage api as well.. This allows you to send messages to another page, and in that page you define an event handler that knows how to handle the message.
This also works across domains.
Here is a blog with an example I just randomly found via google:
http://robertnyman.com/2010/03/18/postmessage-in-html5-to-send-messages-between-windows-and-iframes/
Not possible on the client side if editing the actual HTML file is your goal. If getting pictures to show up depending on stuff a user does on another page is all you care about then there are lots of options.
You can pass small sets of data like stuff the user entered into tables via cookies for accessing the right sets of image files in a pre-established scheme. This would actually persist until a user cleared out cookies.
You could wrap both pages in same-domain iframe elements with the parent element containing just the JS. This would allow you to persist data between pages and react to iframe load events but like everything in client-side JS, it's all gone when you reload the page.
Newer browsers have working file access objects that aren't total security nightmares. These are new and non-standard enough that it would take some doing to make it work for multiple browsers. This could be used to save files containing info that the user would probably have to be prompted to upload when they return to the site.
If the data's not sensitive you could get creative and use another service to stash collections of data. Use a twitter API to tweet data to some publicly visible page of a twitter account (check the Terms of Service if you're doing anything more than an isolated class project here). Then do an Ajax get request on whatever URL it's publicly visible at and parse the HTML for your twitter data.
Other stuff I'd look into: dataURIs, html5 local storage.
Note: None of these are approaches I would seriously consider for a professional site where the data was expected to be persistent or in any way secure regardless of where a user accesses it from.

How to reduce the page load time?

I have a web page I run locally on a WebKit mobile browser (not on a web server) which has around 27 MB of JavaScript files, YES 27 MB of JavaScript files. It is because I have custom JSON objects and arrays hard-coded inside my .js file.
I have split the complete JS contain into 27 small .js files of around 1 MB.
The problem is that when I includes these .js files inside my header, the page load time increases very much.
I'd like to know how can I reduce the page load time in such a case where the js files are required.
1) Is there a way wherein we can inject the .js files inside the HTML after the page loads for the first time? (because the JavaScript content comes into picture only after a link is clicked on the page)
2) What would be an optimium solution to includes such a large JavaScript content inside a web page? I have minified my all js files to reduce the file size as much as possible!
Thanks in advance.
UPDATE 1:
The page runs locally and no WEB SERVER is involved. Finally, it would run inside a mobile browser, and so that's how all the problem arised i.e. the load timing is very high in mobile browser, so want to reduce the initial load time.
(Note: Most of the below was written before you'd bothered to tell us you were running an HTML file locally in a mobile browser without using a web server. Much of it still applies, some of it doesn't, but I've left it for others actually doing web pages.)
1) Is there a way wherein we can inject the .js files inside the HTML after the page loads for the first time?
Yes, it's actually really easy (live example: run / edit):
var script = document.createElement('script');
script.src = "path/to/the/file.js";
document.body.appendChild(script);
Note that the script will load asynchronously (you can't just assume it's loaded after the appendChild call).
But if your goal is just to have the page showing while the 27MB file downloads, you can just put your script tag at the end of your page, just before the closing </body> tag. Update: If you're running a local HTML file, not a web page, I'd think this is all you'd need: A single script tag at the end of the page loading your 27MB .js file.
2) What would be an optimium solution to includes such a large JavaScript content inside a web page?
Ideally, reduce the size if at all possible. If you can demand-load assets as you need them (either using the technique above or ajax), do that instead. Update: If you're running a local file, not a web page, you basically can't do ajax reliably. But you can demand-load what you need, when you need it, via adding script elements as per the above.
Regarding your 27 1MB .js files: If you hardcode the script tags for them, it's much better to do one 27MB file than 27 1MB files. Minimizing HTTP requests to your server (ideally at most one .js file and one .css file) is one of the key ways to improve page load time. In your case, though, you've said various parts aren't needed until various things are clicked, so you'll probably end up with a main file (which will hopefully be a lot smaller than 27MB), and then a bunch of other things you demand load (as per the above) as necessary.
Other things you can do:
Minify, compress, or "compile" your .js files (this means you'll have separate "source" and "production" files, since typically this is a one-way process that removes comments and such)
Ensure that your server is serving .js files with gzip compression (for instance, with Apache you'd use mod_deflate); you can test that it's working with various tools
Also very much worth a read: Best Practices for Speeding Up your Website, which makes the points above and a whole bunch more.
At 27MB it's always going to be slow as you're going to run into the memory limits on the device.
Most mobiles don't have a lot of RAM and once you load and parse the JSON it's going to be using more the 27MB
Minification will help you but gzip won't as the browser still has to decompress it)
If you're just rendering HTML in response to user actions, why don't you create HTML fragments instead of JSON and fetch these and insert them into the DOM when someone clicks on the link?
You have to combine again that *.js files into one. That will reduce the server requests that cost in time !
Compress your JavaScript content with that tool : http://www.refresh-sf.com/yui/ or that http://closure-compiler.appspot.com/home
Also you have to put that files at the page footer, in order to allow the page to be rendered while you download the js files into the client browser.
Another thing that can help is the long time caching of the file. This will allow your JavaScript to be "saved" into client web browser cache and next time is not important to re-downloaded.
Finally I am not 100% sure is that help but try lazy JavaScript loading.
Edit for Lazy Laod
<script type="text/javascript">
(
function()
{
var sc = document.createElement('script');
sc.type = 'text/javascript';
sc.async = true;
sc.src = 'http://www.url-to-your-javascript.file/my-javascript.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(sc,s);
}
)();
</script>
Another helpful source
http://gtmetrix.com/dashboard.html
Tests your web site speed. This will help you find your way on speed optimization about your web site :)
I would load the data after page load with ajax. That is after you loaded the page, you make an asyncronous request for the 27MB of data. This allows you also to eventually add a load animation while the data is transferred. You can have a look at jquery to implement this.
As a best practice, you should always load javascript in bottom oh html file. Put css at top, and js at bottom will greatly help.
27MB is too large. Why are you using hard code in js. you can use ajax. Take help from an expert, may be he can minimize your js
I finally solved over this problem of mine by creating a native application for the mobile device rather than using the hybrid (HTML5) technology i.e. I moved the 27 MB JS files which were containing the actual app data to an sqlite file and used it directly in my Android app.

How do JavaScript-based modal/popup services like KissInsights and Hello Bar work?

I'm developing a modal/popup system for my users to embed in their sites, along the lines of what KissInsights and Hello Bar (example here and here) do.
What is the best practice for architecting services like this? It looks like users embed a bit of JS but that code then inserts additional script tag.
I'm wondering how it communicates with the web service to get the user's content, etc.
TIA
You're right that usually it's simply a script that the customer embeds on their website. However, what comes after that is a bit more complicated matter.
1. Embed a script
The first step as said is to have a script on the target page.
Essentially this script is just a piece of JavaScript code. It's pretty similar to what you'd have on your own page.
This script should generate the content on the customer's page that you wish to display.
However, there are some things you need to take into account:
You can't use any libraries (or if you do, be very careful what you use): These may conflict with what is already on the page, and break the customer's site. You don't want to do that.
Never override anything, as overriding may break the customer's site: This includes event listeners, native object properties, whatever. For example, always use addEventListener or addEvent with events, because these allow you to have multiple listeners
You can't trust any styles: All styles of HTML elements you create must be inlined, because the customer's website may have its own CSS styling for them.
You can't add any CSS rules of your own: These may again break the customer's site.
These rules apply to any script or content you run directly on the customer site. If you create an iframe and display your content there, you can ignore these rules in any content that is inside the frame.
2. Process script on your server
Your embeddable script should usually be generated by a script on your server. This allows you to include logic such as choosing what to display based on parameters, or data from your application's database.
This can be written in any language you like.
Typically your script URL should include some kind of an identifier so that you know what to display. For example, you can use the ID to tell which customer's site it is or other things like that.
If your application requires users to log in, you can process this just like normal. The fact the server-side script is being called by the other website makes no difference.
Communication between the embedded script and your server or frames
There are a few tricks to this as well.
As you may know, XMLHttpRequest does not work across different domains, so you can't use that.
The simplest way to send data over from the other site would be to use an iframe and have the user submit a form inside the iframe (or run an XMLHttpRequest inside the frame, since the iframe's content resides on your own server so there is no cross domain communication)
If your embedded script displays content in an iframe dialog, you may need to be able to tell the script embedded on the customer site when to close the iframe. This can be achieved for example by using window.postMessage
For postMessage, see http://ejohn.org/blog/cross-window-messaging/
For cross-domain communication, see http://softwareas.com/cross-domain-communication-with-iframes
You could take a look here - it's an example of an API created using my JsApiToolkit, a framework for allowing service providers to easily create and distribute Facebook Connect-like tools to third-party sites.
The library is built on top of easyXDM for Cross Domain Messaging, and facilitates interaction via modal dialogs or via popups.
The code and the readme should be sufficient to explain how things fit together (it's really not too complicated once you abstract away things like the XDM).
About the embedding itself; you can do this directly, but most services use a 'bootstrapping' script that can easily be updated to point to the real files - this small file could be served with a cache pragma that would ensure that it was not cached for too long, while the injected files could be served as long living files.
This way you only incur the overhead of re-downloading the bootstrapper instead of the entire set of scripts.
Best practice is to put as little code as possible into your code snippet, so you don't ever have to ask the users to update their code. For instance:
<script type="text/javascript" src="http://your.site.com/somecode.js"></script>
Works fine if the author will embed it inside their page. Otherwise, if you need a bookmarklet, you can use this code to load your script on any page:
javascript:(function(){
var e=document.createElement('script');
e.setAttribute('language','javascript');
e.setAttribute('src','http://your.site.com/somecode.js');
document.head.appendChild(e);
})();
Now all your code will live at the above referenced URI, and whenever their page is loaded, a fresh copy of your code will be downloaded and executed. (not taking caching settings into account)
From that script, just make sure that you don't clobber namespaces, and check if a library exists before loading another. Use the safe jQuery object instead of $ if you are using that. And if you want to load more external content (like jQuery, UI stuff, etc.) use the onload handler to detect when they are fully loaded. For example:
function jsLoad(loc, callback){
var e=document.createElement('script');
e.setAttribute('language','javascript');
e.setAttribute('src',loc);
if (callback) e.onload = callback;
document.head.appendChild(e);
}
Then you can simply call this function to load any js file, and execute a callback function.
jsLoad('http://link.to/some.js', function(){
// do some stuff
});
Now, a tricky way to communicate with your domain to retrieve data is to use javascript as the transport. For instance:
jsLoad('http://link.to/someother.js?data=xy&callback=getSome', function(){
var yourData = getSome();
});
Your server will have to dynamically process that route, and return some javascript that has a "getSome" function that does what you want it to. For instance:
function getSome(){
return {'some':'data','more':'data'};
}
That will pretty effectively allow you to communicate with your server and process data from anywhere your server can get it.
You can serve a dynamically generated (use for example PHP or Ruby on Rails) to generate this file on each request) JS file from your server that is imported from the customers web site like this:
<script type="text/javascript" src="//www.yourserver.com/dynamic.js"></script>
Then you need to provide a way for your customer to decide what they want the modal/popup to contain (e.g. text, graphics, links etc.). Either you create a simple CMS or you do it manually for each customer.
Your server can see where each request for the JS file is coming from and provide different JS code based on that. The JS code can for example insert HTML code into your customers web site that creates a bar at the top with some text and a link.
If you want to access your customers visitors info you probably need to either read it from the HTML code, make your customers provide the information you want in a specific way or figure out a different way to access it from each customers web server.

Categories

Resources