Javascript - To combine or not combine, that is the question - javascript

Ok, so I know that it's obvious to combine all of a pages Javascript into a single external file for efficiency purposes, but that's not quite the question here.
Say I have Default.htm with a search field that has a little Javascript magic attached to it. Then I have Contact.htm with a contact form that has some Javascript magic attached to it. And finally I have a FAQ.htm with some jQuery panels showing the answers... you get the picture.
Basically I have three pages that all have "some" javascript need, but none of the Javascript is used on any other pages.
Is it better to combine all of that Javascript into one big minified file that loads once and is then stored in Cache, or is it better to use an individual Javascript file on the Default page, but not use it on the Contact page... etc?
What works best in this scenario?
Option: 1
Default.htm
jquery.js
default.js
Contact.htm
jquery.js
contact.js
Faq.htm
jquery.js
faq.js
Option: 2
Default.htm
jquery-default-contact-faq-min.js
Contact.htm
jquery-default-contact-faq-min.js
Faq.htm
jquery-default-contact-faq-min.js
PS: for all you asp.net guys, I'm using Combres to Combine, Minify, and Version my Javascript files

I would definitely vote to combine them. If you are concerned about parse or setup time for the "not used" Javascript, then I would recommend structuring your Javascript with each file in a closure, and then run the closures you need on the pages you need them. For example:
// File 1
window.closures = window.closures || {}
window.closures["page1"] = (function() {
// Javascript for Page 1
});
// File 2
window.closures = window.closures || {}
window.closures["page2"] = (function() {
// Javascript for Page 2
});
// File 3
window.closures = window.closures || {}
window.closures["page2"] = (function() {
// Javascript for Page 2
});
Then, in your page:
<!-- This one combined.js file will be downloaded once and cached //-->
<script type="text/javascript" src="combined.js"></script>
<script>
// Run the Javascript in your combined.js intended for page2
window.closures["page2"]()
</script>

combine into 1 file. let it get cached. it loads once on any page, and for any subsequent pages it can use the cached copy.

Because it doesn't sound like there's a lot of javascript, combining it into one file would be better. Only if there's significant amounts of javascript that doesn't need to be loaded if a user doesn't visit a page then you would consider keeping the files separate.

It is always an act of balancing the number of HTTP requests and limiting the transferred bytes that are not really needed yet.
There are three possibilities:
combine everything in 1 file
have three separate files, and load them as needed
have three separate files, load the one needed for that page right away and preload the others (when the time is right)
You will only know what is best for your situation by doing some A-B load testing.
Everything depends on the size of the transferred data, the overlap of needed functionality and the probability that some functionality is needed.

If the combined file is under say, 25kb minified, then go for it. But if it is more than that, I'd say, identify the one that is the biggest of them, and let that one js file be separate. Combine the rest. That 25kb limit thingy too is not a hard rule, it is up to you.
If your individual files are in the magnitude of say, 30kb, I'd recommend not combining them, and letting the individual js files be cached as individual js files.
Hope that helps.

Related

How to have one main JavaScript file for multiple pages?

I have a small application with two pages: the login page and the main page. My problem is that when I use just one main JavaScript file for both pages (like it's recommanded) I get a lot of ReferenceError because some variables on a page are not defined on the other one...
e.g:
Line of code for the login page
copyrightYear.textContent = new Date().getFullYear();
Main page complains
Uncaught TypeError: Cannot set property 'textContent' of null
How can I fix that? Don't tell me I have to say if(copyrightYear) { do stuff } everytime, it's just a nightmare if I have to do that for every variable
Two answers for you:
The recommendation isn't a dictate
My problem is that when I use just one main JavaScript file for both pages (like it's recommanded)
That's a very general recommendation. It doesn't apply to every situation. There's no point in loading code in a page that won't use that code.
If you have code that you use in both pages, and also page-specific code, it's absolutely fine to have a file that both pages share and also page-specific files:
<script src="main.js"></script>
<script src="page1.js"></script>
If you're really worried about the extra HTTP request (much less of an issue these days than it used to be), use modules and a bundler like Webpack or Rollup that will create a bundle combining the main module with page 1's module for page 1 and another bundle combining the main module with page 2's module for page 2.
But even then, the extra HTTP request may be better for your users, if you expect them to go from page1 to page2 in a reasonable timeframe. The reason is that if you have main.js and page1.js/page2.js and you allow caching of them, when the user goes to page1 they get main.js and page1.js, and then when they go to page2 main.js comes out of their local cache and they only have to load page2.js. In contrast, if you had a single bundle file for each page, they'd have to re-download all of that common code when going from page1 to page2 (or vice versa). But if you expect a visitor to visit either page1 or page2 but not the other one, you save the HTTP request by using page-specific bundles.
There's really no one-size-fits-all solution. :-) There are all sorts of considerations.
Note that HTTP/1.1 made additional HTTP requests more efficient and is nearly universally supported, and HTTP/2 makes them a lot more efficient, effectively eliminating the case for reducing the number of HTTP requests as part of the page startup. All major modern browsers support HTTP/2 as do up-to-date web servers.
Put the code for each page in a function
If you really want to keep a single page, put the code that's specific to each page in functions for those pages, and then have code in the main part of the file call the appropriate function based on location.pathname.
You figured it out, you have to check this for every variable. But generally it's much more convenient to use functions and only call these functions when you need them.
So for example, say you want to set some copyrightYear (even tough this shouldn't be set via JS, you should generate this on Backend side to have it in the source code)
You have something like this:
function updateYear() {
// here you do your magic of selecting the element, setting the year, whatever.
}
// another function, totally unrealted to updateYear()
function toggleMenu() {
// some function where you toggle the menu if you click somewhere
// like: button.addEventListener('click', () => {} );
}
And in your JS file you have one block where you call all these functions:
if (document.querySelectorAll('.elementForYear') {
updateYear(); // here we call it because we are sure this element exists... so everything inside function must work
}
if (document.querySelector('.myMenu') {
toggleMenu(); // if the element myMenu exists, we know we can add these toggle Functionality.
}
You can also add these if inside the function and call the function regardless of if it's needed or not, that's up to you and up to coding guidelines.
Generally I find it makes sense to have one function only rely on one (or max two to three elements if it's some toggling of other elements) ... And then you just check for one element. And if this one element exists you can go ahead and call the function.

How/when/where to include external javascript

I'm looking for some advice on the best way to hold my JavaScript (jQuery) functions.
I am developing in MVC/razor and therefore have a layout page. I include my jQuery library and an external JavaScript file in here so it's available in every single page.
This is working well, but I am now becoming very aware of the fact that I am adding almost 300 lines of JS to EVERY page, where maybe half of that is used in any one of these pages.
One function is not in the external file and instead sits inside the HTML because I need to use variables set in my razor code.
I have a couple of questions around this arrangement:
Is placing JS inside the HTML generally acceptable when variables set using razor are used? There does not appear to be a clean way of passing a variable into an external js file
Should I split my functions down in to individual JS files and just include what is needed for each page in the site?
If I were to split them into multiple files, how would that work with jQuery's (document).ready ? Do I need to use that if all the JavaScript I am including is to be used?
I'm sure this will more a matter of opinion than a black and white answer, but I want to consider all my options before moving on. Even though it works fine as is, I can't help but feel there is a better/cleaner way.
Remember once a user lands on your homepage and loads the javascript file it will be cached in their browser so subsequent pages will not download the Javascript again.
I would definitely keep the js separate, you could have a snippet on each page that initialise the JS that that particurlar view needs. Put something like the below in the views that need to run JS
$(document).ready(function() {
mysite.mypage();
});
Then the function mysite.mypage() can be defined in the external JS file.
300 lines isnt the end of the world, I would say its probably too early to be worryign about optimisation.
You could always look at minifying that JS file to decrease the size. A quick and easy way to do this is here:
http://www.minifyjavascript.com/
Have you ever heard of require.js? http://requirejs.org/ I find it really useful.
It's a module loader so you are able to split all of your JS code into individual files and load only the ones you need on each page.
I don't know about passing a variable to an external JS file, I don't think its possible / the 'right' way.
You can make each external JS file into a function that accepts and returns parameters. Then in the page you need to use it:
- include the file dependancy
- call the function
Thats what I do, seems like your 2nd suggestion.
for the $(document.ready) question its really up to you. You don't have to use it but its useful for some things , check out this overview:
http://docs.jquery.com/Tutorials:Introducing_$(document).ready()

One JavaScript File Per Page or Combine when using Jquery and Document Ready Function

Ok So I know it always depends on the situation but I have, thus far, combined my jquery files/plugins into a single compressed file.
Now I am wondering what I should do with my page specific js/jQuery code. Should I have a single file with one Document.Ready function and my entires sites js code inside of it? Or split it up into seperate js files per page with a document ready call in each?
These files will inclide things such as .Click handlers and other jquery code specific to certain pages.
Whats the best practice here to optimize load times and maintainabilty?
One way to do it would be to use require.js and then have an array with files and page types. Give each body tag an ID and use it to reference what files should be loaded in.
<body id="pageName">
Keep your global files everything you need for the core functionality to work and then lazy load in the features that aren't required for your site to run faster. I've seen huge speed improvements from this technique.
http://requirejs.org/
We can do this in multiple ways , i did in the following way.
Aggregate your files broadylyas following
1) Aggregate all the files required for all the pages
2) aggregate the pages specific to the page.
Include all the common aggregated file for all the pages , and include other aggregated files conditionally on the page
1) jquery and other plugins common to all pages so // it will go to all files
2) homepage-aggregation /// for homepage
3) gallerypage-aggregation // for gallery page.
If you include the same file for all the pages ,it may not necessary for all the files.
I did it recently , let me know if you need anything else
Because you're almost certain to want to have different things executed in the Document.Ready function depending on what page you're on I don't think that having one function that is executed on every page is helpful.
Personally I mix my $.ready calls in with my HTML. These are simple calls to functions stored in a single, minimizing javascript file so don't take up too many bytes, and prevent the need for a separate Javascript file per page. It also allows me to initiate the Javascript where I create the markup, so it's all in one place.
If you're minimizing your javascript and serving it with the correct headers you've got most of the benefits already, don't compromise readability more than you have to.
It also depends on the server side technology you are using. You may find tools to assist you on this task. If you are coding a Java server side, you may try JAWR. It allows the creation of separated JS/CSS files, merging and compressing them server-side, turning all the separate files into a single file.
About Document.Ready, I prefer to keep specific code page in separate files, avoiding incorrect code execution and behavior. It is also cleaner and easier to maintain.

Browser performance impact of lots of js includes

I'm working on a website for work that uses one master layout for the whole site which includes lots (over 40) js files. This website is really slow to render. How much overhead is there for the browser to parse and (for a lack of better technical term) "deal with" all these includes? I know that they are cached, so they are not being downloaded on each page view. However, does each include get parsed and executed anew on every page refresh?
At any rate, I imagine there is some overhead in dealing with all these includes, but I'm not sure if it's big or small.
The best way to understand is to measure. Try merging those 40 js files into a single one and see if it makes a big difference. Also compressing them could reduce bandwidth costs.
There will be an overhead of having multiple includes but as you say those pages are cached and the overhead should be only on the first request. I think that if we ignore this initial overhead the performance difference won't be enormous compared to the time spent in those scripts manipulating the DOM, etc...
it depends on what they do - to test you could do this before they are all loaded:
<script>
var test_start_time = (new Date()).getTime();
</script>
and this after:
<script>
alert("took: " + (((new Date()).getTime()-test_start_time)/1000) + " seconds");
</script>
Definitely compare and contrast - that will be the most reliable judge.
Nevertheless, I do my best to only load one or two JS files in the head section, then I use jquery to test for certain elements which might require additional scripts or css once the DOM is loaded. For example, I use the source highlight js library to stylize pre tags:
if($('pre').length > 0) {
$.getScript(svx_cdns+'pkgs/shjs-0.6/sh_main.min.js', function() {
$('<link>', {
'rel': 'stylesheet',
'type': 'text/css',
'href': svx_cdns+'pkgs/shjs-0.6/css/sh_vim.min.css'
}).appendTo('head');
sh_highlightDocument('/s/pkgs/shjs-0.6/lang/', '.min.js');
});
}
That way the page loads very quickly, and then "adjusts" afterwards.
You could try to put all of the .js files into one file and then compress it.
This will lower the amount of requests made by the browser by 39 as well :).
Hope this helped.
The impact may be important. Take into account that script downloading blocks page rendering
A couple of things you may try:
Combine as many scripts as you can so you download less files
Minimize and compress combined js files
Try to put as many references as you can at the bottom of the page so they don't block the rendering (this is not easy and must be done carefully, you might end up allowing interaction with some controls before the necessary javascript is downloaded).
Implement paralell download for js files (by default they are downloaded sequentially). Here you have some examples about that
Even if the files are cached, there's still a request to check if the file has been modified. You can change your caching strategy and set your files never to expire. That way the browser will not even ask if it's been modified. That will mean you'll need to add a cache buster to all your urls. Look at firebug's net tab to be sure. I get a 304 Not modified with all my css/js/imgs.
The files are going to have to be parsed everytime, but that's probably not the bottleneck.
Try copying all your js into one file. One of our screen was including over 100 js files. We created a unified minimized file and our screen load time went from 10 seconds to less then 3.

Where to put JavaScript configuration functions?

What is the general developer opinion on including javascript code on the file instead of including it on the script tag.
So we all agree that jquery needs to be included with a script file, like below:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"
type="text/javascript"></script>
My question is, in order to get functions on a page that is not on all pages of a site. Do we include the functions like below in the same page or in a global include file like above called mysite.js.
$(document).ready(function(){
$(".clickme").click(function(event){
alert("Thanks for visiting!");
});
});
ok. So the question is: if the code above is going to be called in every class="clickme" on a specific pages, and you have the ability to call it either from an include separate file called mysite.js or in the content of the page. Which way will you go?
Arguments are:
If you include it on the page you will only call it from those specific pages that the js functionality is needed.
Or you include it as a file, which the browser cached, but then jquery will have to spend x ms to know that that function is not trigger on a page without "clickme" class in it.
EDIT 1:
Ok. One point that I want to make sure people address is what is the effect of having the document.ready function called things that does not exist in the page, will that trigger any type of delay on the browser? Is that a significant impact?
First of all - $("#clickme") will find the id="clickme" not class="clickme". You'd want $(".clickme") if you were looking for classes.
I (try to) never put any actual JavaScript code inside my XHTML documents, unless I'm working on testing something on a page quickly. I always link to an external JS file to load the functionality I want. Browsers without JS (like web crawlers) will not load these files, and it makes your code look much cleaner to the "view source".
If I need a bit of functionality only on one page - it sometimes gets its own include file. It all depends on how much functionality / slow selectors it uses. Just because you put your JS in an external JS file doesn't mean you need to include it on every page.
The main reason I use this practice - if I need to change some JavaScript code, it will all be in the same place, and change site wide.
As far as the question about performance goes- Some selectors take a lot of time, but most of them (especially those that deal with ID) are very quick. Searching for a selector that doesn't exist is a waste of time, but when you put that up against the wasted time of a second script HTTP request (which blocks the DOM from being ready btw), searching for an empty selector will generally win as being the lesser of the two evils. jQuery 1.3 Performace Notes and SlickSpeed will hopefully help you decide on how many MS you really are losing to searching for a class.
I tend to use an external file so if a change is needed it is done in one place for all pages, rather than x changes on x pages.
Also if you leave the project and someone else has to take over, it can be a massive pain to dig around the project trying to find some inline js.
My personal preference is
completely global functions, plugins and utilities - in a separate JavaScript file and referenced in each page (much like the jQuery file)
specific page functionality - in a separate JavaScript file and only referenced in the page it is needed for
Remember that you can also minify and gzip the files too.
I'm a firm believer of Unobtrusive JavaScript and therefore try to avoid having any JavaScript code in with the markup, even if the JavaScript is in it's own script block.
I agreed to never have code in your HTML page. In ASP.net I programmatically have added a check for each page to see if it has a same name javascript file.
Eg. MyPage.aspx will look for a MyPage.aspx.js
For my MVC master page I have this code to add a javascript link:
// Add Each page's javascript file
if (Page.ViewContext.View is WebFormView)
{
WebFormView view = Page.ViewContext.View as WebFormView;
string shortUrl = view.ViewPath + ".js";
if (File.Exists(Server.MapPath(shortUrl)))
{
_clientScriptIncludes["PageJavascript"] = Page.ResolveUrl(shortUrl);
}
}
This works well because:
It is automagically included in my files
The .js file lives alongside the page itself
Sorry if this doesn't apply to your language/coding style.

Categories

Resources