Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I split my javascript into multiple files?

I'm used to working with Java in which (as we know) each object is defined in its own file (generally speaking). I like this. I think it makes code easier to work with and manage.

I'm beginning to work with javascript and I'm finding myself wanting to use separate files for different scripts I'm using on a single page. I'm currently limiting myself to only a couple .js files because I'm afraid that if I use more than this I will be inconvenienced in the future by something I'm currently failing to foresee. Perhaps circular references?

In short, is it bad practice to break my scripts up into multiple files?

like image 892
Peter Berg Avatar asked Mar 13 '13 22:03

Peter Berg


People also ask

Should I separate JavaScript files?

You should put your JS code in a separate file because this makes it easier to test and develop. The question of how you serve the code is a different matter. Serving the HTML and the JS separately has the advantage that a client can cache the JS.

Should all my JavaScript be in one file?

To avoid multiple server requests, group your JavaScript files into one. Whatever you use for performance, try to minify JavaScript to improve the load time of the web page. If you are using single page application, then group all the scripts in a single file.

Should I split my code into multiple files?

Splitting your code into multiple files is a great way to produce smaller, more focused files. Navigating theses smaller files will be easier and so will understanding the content of each of these files.

What is better to load one complete JavaScript file on all pages or separate files based on different pages?

It is best to keep separate files or include all files in one file Javascript? To avoid multiple server requests, it is better to group all your JavaScript files into only one. If you're using C#.Net + ASP.Net, you can bundle your files — it is a very good way to compress your scripts.


2 Answers

There are lots of correct answers, here, depending on the size of your application and whom you're delivering it to (by whom, I mean intended devices, et cetera), and how much work you can do server-side to ensure that you're targeting the correct devices (this is still a long way from 100% viable for most non-enterprise mortals).

When building your application, "classes" can reside in their own files, happily.
When splitting an application across files, or when dealing with classes with constructors that assume too much (like instantiating other classes), circular-references or dead-end references ARE a large concern.
There are multiple patterns to deal with this, but the best one, of course is to make your app with DI/IoC in mind, so that circular-references don't happen.
You can also look into require.js or other dependency-loaders. How intricate you need to get is a function of how large your application is, and how private you would like everything to be.

When serving your application, the baseline for serving JS is to concatenate all of the scripts you need (in the correct order, if you're going to instantiate stuff which assumes other stuff exists), and serve them as one file at the bottom of the page.

But that's baseline.
Other methods might include "lazy/deferred" loading.
Load all of the stuff that you need to get the page working up-front.
Meanwhile, if you have applets or widgets which don't need 100% of their functionality on page-load, and in fact, they require user-interaction, or require a time-delay before doing anything, then make loading the scripts for those widgets a deferred event. Load a script for a tabbed widget at the point where the user hits mousedown on the tab. Now you've only loaded the scripts that you need, and only when needed, and nobody will really notice the tiny lag in downloading.

Compare this to people trying to stuff 40,000 line applications in one file.
Only one HTTP request, and only one download, but the parsing/compiling time now becomes a noticeable fraction of a second.

Of course, lazy-loading is not an excuse for leaving every class in its own file.
At that point, you should be packing them together into modules, and serving the file which will run that whole widget/applet/whatever (unless there are other logical places, where functionality isn't needed until later, and it's hidden behind further interactions).

You could also put the loading of these modules on a timer.
Load the baseline application stuff up-front (again at the bottom of the page, in one file), and then set a timeout for a half-second or so, and load other JS files.
You're now not getting in the way of the page's operation, or of the user's ability to move around. This, of course is the most important part.

like image 133
Norguard Avatar answered Oct 10 '22 15:10

Norguard


Update from 2020: this answer is very old by internet standards and is far from the full picture today, but still sees occasional votes so I feel the need to provide some hints on what has changed since it was posted. Good support for async script loading, HTTP/2's server push capabilities, and general browser optimisations to the loading process over the years, have all had an impact on how breaking up Javascript into multiple files affects loading performance.

For those just starting out with Javascript, my advice remains the same (use a bundler / minifier and trust it to do the right thing by default), but for anybody finding this question who has more experience, I'd invite them to investigate the new capabilities brought with async loading and server push.

Original answer from 2013-ish:


Because of download times, you should always try to make your scripts a single, big, file. HOWEVER, if you use a minifier (which you should), they can combine multiple source files into one for you. So you can keep working on multiple files then minify them into a single file for distribution.

The main exception to this is public libraries such as jQuery, which you should always load from public CDNs (more likely the user has already loaded them, so doesn't need to load them again). If you do use a public CDN, always have a fallback for loading from your own server if that fails.

As noted in the comments, the true story is a little more complex;

Scripts can be loaded synchronously (<script src="blah"></script>) or asynchronously (s=document.createElement('script');s.async=true;...). Synchronous scripts block loading other resources until they have loaded. So for example:

<script src="a.js"></script> <script src="b.js"></script> 

will request a.js, wait for it to load, then load b.js. In this case, it's clearly better to combine a.js with b.js and have them load in one fell swoop.

Similarly, if a.js has code to load b.js, you will have the same situation no matter whether they're asynchronous or not.

But if you load them both at once and asynchronously, and depending on the state of the client's connection to the server, and a whole bunch of considerations which can only be truly determined by profiling, it can be faster.

(function(d){     var s=d.getElementsByTagName('script')[0],f=d.createElement('script');     f.type='text/javascript';     f.async=true;     f.src='a.js';     s.parentNode.insertBefore(f,s);     f=d.createElement('script');     f.type='text/javascript';     f.async=true;     f.src='b.js';     s.parentNode.insertBefore(f,s); })(document) 

It's much more complicated, but will load both a.js and b.js without blocking each other or anything else. Eventually the async attribute will be supported properly, and you'll be able to do this as easily as loading synchronously. Eventually.

like image 31
Dave Avatar answered Oct 10 '22 15:10

Dave