What are some standard practices for managing a medium-large JavaScript application? My concerns are both speed for browser download and ease and maintainability of development.
Our JavaScript code is roughly "namespaced" as:
var Client = {
var1: '',
var2: '',
accounts: {
/* 100's of functions and variables */
},
orders: {
/* 100's of functions and variables and subsections */
}
/* etc, etc for a couple hundred kb */
}
At the moment, we have one (unpacked, unstripped, highly readable) JavaScript file to handle all the business logic on the web application. In addition, there is jQuery and several jQuery extensions. The problem we face is that it takes forever to find anything in the JavaScript code and the browser still has a dozen files to download.
Is it common to have a handful of "source" JavaScript files that gets "compiled" into one final, compressed JavaScript file? Any other handy hints or best practices?
The approach that I've found works for me is having seperate JS files for each class (just as you would in Java, C# and others). Alternatively you can group your JS into application functional areas if that's easier for you to navigate.
If you put all your JS files into one directory, you can have your server-side environment (PHP for instance) loop through each file in that directory and output a <script src='/path/to/js/$file.js' type='text/javascript'> in some header file that is included by all your UI pages. You'll find this auto-loading especially handy if you're regularly creating and removing JS files.
When deploying to production, you should have a script that combines them all into one JS file and "minifies" it to keep the size down.
Also, I suggest you to use Google's AJAX Libraries API in order to load external libraries.
It's a Google developer tool which bundle majors JavaScript libraries and make it easier to deploy, upgrade and make them lighter by always using compressed versions.
Also, it make your project simpler and lighter because you don't need to download, copy and maintain theses libraries files in your project.
Use it this way :
google.load("jquery", "1.2.3");
google.load("jqueryui", "1.5.2");
google.load("prototype", "1.6");
google.load("scriptaculous", "1.8.1");
google.load("mootools", "1.11");
google.load("dojo", "1.1.1");
Just a sidenode - Steve already pointed out, you should really "minify" your JS files. In JS, whitespaces actually matter. If you have thousand lines of JS and you strip only the unrequired newlines you have already saved about 1K. I think you get the point.
There are tools, for this job. And you should never modify the "minified"/stripped/obfuscated JS by hand! Never!
In our big javascript applications, we write all our code in small separate files - one file per 'class' or functional group, using a kind-of-like-Java namespacing/directory structure. We then have:
A compile-time step that takes all our code and minifies it (using a variant of JSMin) to reduce download size
A compile-time step that takes the classes that are always or almost always needed and concatenates them into a large bundle to reduce round trips to the server
A 'classloader' that loads the remaining classes at runtime on demand.
For server efficiency's sake, it is best to combine all of your javascript into one minified file.
Determine the order in which code is required and then place the minified code in the order it is required in a single file.
The key is to reduce the number of requests required to load your page, which is why you should have all javascript in a single file for production.
I'd recommend keeping files split up for development and then create a build script to combine/compile everything.
Also, as a good rule of thumb, make sure you include your JavaScript toward the end of your page. If JavaScript is included in the header (or anywhere early in the page), it will stop all other requests from being made until it is loaded, even if pipelining is turned on. If it is at the end of the page, you won't have this problem.
Read the code of other (good) javascript apps and see how they handle things. But I start out with a file per class. But once its ready for production, I would combine the files into one large file and minify.
The only reason, I would not combine the files, is if I didn't need all the files on all the pages.
My strategy consist of 2 major techniques: AMD modules (to avoid dozens of script tags) and the Module pattern (to avoid tightly coupling of the parts of your application)
AMD Modules: very straight forward, see here: http://requirejs.org/docs/api.html also it's able to package all the parts of your app into one minified JS file: http://requirejs.org/docs/optimization.html
Module Pattern: i used this Library: https://github.com/flosse/scaleApp you asking now what is this ? more infos here: http://www.youtube.com/watch?v=7BGvy-S-Iag
Related
What are some standard practices for managing a medium-large JavaScript application? My concerns are both speed for browser download and ease and maintainability of development.
Our JavaScript code is roughly "namespaced" as:
var Client = {
var1: '',
var2: '',
accounts: {
/* 100's of functions and variables */
},
orders: {
/* 100's of functions and variables and subsections */
}
/* etc, etc for a couple hundred kb */
}
At the moment, we have one (unpacked, unstripped, highly readable) JavaScript file to handle all the business logic on the web application. In addition, there is jQuery and several jQuery extensions. The problem we face is that it takes forever to find anything in the JavaScript code and the browser still has a dozen files to download.
Is it common to have a handful of "source" JavaScript files that gets "compiled" into one final, compressed JavaScript file? Any other handy hints or best practices?
The approach that I've found works for me is having seperate JS files for each class (just as you would in Java, C# and others). Alternatively you can group your JS into application functional areas if that's easier for you to navigate.
If you put all your JS files into one directory, you can have your server-side environment (PHP for instance) loop through each file in that directory and output a <script src='/path/to/js/$file.js' type='text/javascript'> in some header file that is included by all your UI pages. You'll find this auto-loading especially handy if you're regularly creating and removing JS files.
When deploying to production, you should have a script that combines them all into one JS file and "minifies" it to keep the size down.
Also, I suggest you to use Google's AJAX Libraries API in order to load external libraries.
It's a Google developer tool which bundle majors JavaScript libraries and make it easier to deploy, upgrade and make them lighter by always using compressed versions.
Also, it make your project simpler and lighter because you don't need to download, copy and maintain theses libraries files in your project.
Use it this way :
google.load("jquery", "1.2.3");
google.load("jqueryui", "1.5.2");
google.load("prototype", "1.6");
google.load("scriptaculous", "1.8.1");
google.load("mootools", "1.11");
google.load("dojo", "1.1.1");
Just a sidenode - Steve already pointed out, you should really "minify" your JS files. In JS, whitespaces actually matter. If you have thousand lines of JS and you strip only the unrequired newlines you have already saved about 1K. I think you get the point.
There are tools, for this job. And you should never modify the "minified"/stripped/obfuscated JS by hand! Never!
In our big javascript applications, we write all our code in small separate files - one file per 'class' or functional group, using a kind-of-like-Java namespacing/directory structure. We then have:
A compile-time step that takes all our code and minifies it (using a variant of JSMin) to reduce download size
A compile-time step that takes the classes that are always or almost always needed and concatenates them into a large bundle to reduce round trips to the server
A 'classloader' that loads the remaining classes at runtime on demand.
For server efficiency's sake, it is best to combine all of your javascript into one minified file.
Determine the order in which code is required and then place the minified code in the order it is required in a single file.
The key is to reduce the number of requests required to load your page, which is why you should have all javascript in a single file for production.
I'd recommend keeping files split up for development and then create a build script to combine/compile everything.
Also, as a good rule of thumb, make sure you include your JavaScript toward the end of your page. If JavaScript is included in the header (or anywhere early in the page), it will stop all other requests from being made until it is loaded, even if pipelining is turned on. If it is at the end of the page, you won't have this problem.
Read the code of other (good) javascript apps and see how they handle things. But I start out with a file per class. But once its ready for production, I would combine the files into one large file and minify.
The only reason, I would not combine the files, is if I didn't need all the files on all the pages.
My strategy consist of 2 major techniques: AMD modules (to avoid dozens of script tags) and the Module pattern (to avoid tightly coupling of the parts of your application)
AMD Modules: very straight forward, see here: http://requirejs.org/docs/api.html also it's able to package all the parts of your app into one minified JS file: http://requirejs.org/docs/optimization.html
Module Pattern: i used this Library: https://github.com/flosse/scaleApp you asking now what is this ? more infos here: http://www.youtube.com/watch?v=7BGvy-S-Iag
This may be a dumb question for web guys. But I am a little confused over this. Now, I have an application where I am using a couple of Javascript files to perform different tasks. Now, I am using Javascript bundler to combine and minify all the files. So, at runtime there will be only one app.min.js file. Now, Requirejs is used to load modules or files at runtime. So, the question is if I already have all things in one file, then do I need requirejs? Or what is a use case scenario where I can use requirejs and/or bundler?
Please let me know if any further details are needed.
Generally you only use RequireJS in its loading form during development. Once the site is done and ready for deployment, you minify the code. The advantage here is RequireJS knows exactly what your dependencies are, and thus can easily minify the code in the correct order. Here is what it says on the RequireJS website:
Once you are finished doing development and want to deploy your code for your end users, you can use the optimizer to combine the JavaScript files together and minify it. In the example above, it can combine main.js and helper/util.js into one file and minify the result.
This is a hotly contested issue among many proficient javascript developers. Many other languages have a "compilation" phase where the entire program is bundled up for deployment (JBoss's .WAR files come to mind). Programmers that come from more traditional backgrounds often favor this approach.
Javascript has seen such growth in recent years that it is difficult to chart exact best practices, but those that appreciate the more functional nature of Javascript often prefer the module loading approach (like require.js uses).
I wrote Frame.js which works much like require.js, so my bias is towards the module loader approach.
To answer your question directly, yes, it is one or the other.
Most that argue for packing your scripts into a single file believe it enables more compression and is thus more efficient. I believe the efficiency advantages of packaging are negligible in most cases because: (1) module load times are distributed over the entire session, (2) individual modules can be compressed to nearly the same percentage, (3) individual modules can be cached by the server and routers separately, and (4) loading scripts only when they are needed ultimately allows you load less code for some users and more code overall.
In the long run, if you can see an advantage to dynamic script loading use it. If not, bundle your scripts into a single file.
It depends on your application. If you're making a server-side app with only modest javascript (less than 100kb minified) then go for total bundling, you're probably going to be fine.
But if you're making a javascript app and have a ton of code in it, then your needs are going to be different.
For example, in my app I bundle all the core files. There's jQuery, underscore, backbone, my main app files, my user login system, my layout system, my notifications and chat system, all are part of my big initial file.
But I have many other modules as well that isn't part of the initial bundle, that are loaded after those.
The forums, the wiki, the wysiwyg, color picker, drag/drop, calendar, and some animation files are part of the second category. You need to make reasonable decisions about what's commonly used and needed immediately vs what can be delayed.
If I include everything immediately I can get above a meg of javascript, which would be insane and make the initial boot unacceptably slow.
The second category starts downloading after initSuccess event fires from the initial file.
But the second category is more intelligent than the first in that it loads what's more important first. For example if you're looking at the wiki it'll load the wiki before it loads the color picker.
I know questions around javascript compression have been asked multiple times but I cannot find any answering my problem.
I have a project that has common scripts (jQuery and a few others) and page specific ones. jQuery Mobile allows you to cache common scripts during a session by downloading anything that is in <head> only once. The specific scripts are pulled only if the page is loaded as long as you put the <script> in the <div data-role="page">.
I find this great because it optimizes scripts that are downloaded while browsing the pages of my app and ensures the browser has the minimum javascript in memory at any time.
However, it is terrible for minification because there are dependencies between various files that cannot be merged.
So far I found two solutions that do not suit me so well:
using a simple minification script that does not change function and variable names: it doubles the size of the files compared to an advanced version
grouping all the scripts into one and compress it then put it in the <head>: you lose the ability to only download the scripts you may want and the browser has unnecessary functions loaded
(I exclude manually changing the function names obviously ;) )
I am looking for a compressor that could do one of those:
compress all the files together but output them into seperate files to keep the modularity
if not possible, compress files independently in an advanced way but with tags that could prevent the minifier from renaming links to external functions or variables (such as jQuery ones)
Does it exist?
After getting more familiar with all this, Google Closure Compiler can do that (and much more).
The way to go is to define externs for:
the third party library you are using (jQuery, jQuery Mobile...). You can find some of them there.
the home made scripts that you load seperately
Obviously, if you compress the home made scripts that are loaded separately, you should export the variables you want to use elsewhere using the following technique (detailed in Closure Compiler documentation) :
/**
* A function you want to be able to call from elsewhere after compressing
* #param {string} a
*/
function exportedFunction(a) {alert(a);}
window['exportedFunction'] = exportedFunction;
Then you can compress files you want in batches or separately. It is such a powerful tool that I cannot believe I did not use it before.
I have had some thoughts recently on how to handle shared javascript and css files across a web application.
In a current web application that I am working on, I got quite a large number of different javascripts and css files that are placed in an folder on the server. Some of the files are reused, while others are not.
In a production site, it's quite stupid to have a high number of HTTP requests and many kilobytes of unnecessary javascript and redundant css being loaded. The solution to that is of course to create one big bundled file per page that only contains the necessary information, which then is minimized and sent compressed (GZIP) to the client.
There's no worries to create a bundle of javascript files and minimize them manually if you were going to do it once, but since the app is continuously maintained and things do change and develop, it quite soon becomes a headache to do this manually while pushing out new updates that features changes to javascripts and/or css files to production.
What's a good approach to handle this? How do you handle this in your application?
I built a library, Combres, that does exactly that, i.e. minify, combine etc. It also automatically detects changes to both local and remote JS/CSS files and push the latest to the browser. It's free & open-source. Check this article out for an introduction to Combres.
I am dealing with the exact same issue on a site I am launching.
I recently found out about a project named SquishIt (see on GitHub). It is built for the Asp.net framework. If you aren't using asp.net, you can still learn about the principles behind what he's doing here.
SquishIt allows you to create named "bundles" of files and then to render those combined and minified file bundles throughout the site.
CSS files can be categorized and partitioned to logical parts (like common, print, vs.) and then you can use CSS's import feature to successfully load the CSS files. Reusing of these small files also makes it possible to use client side caching.
When it comes to Javascript, i think you can solve this problem at server side, multiple script files added to the page, you can also dynamically generate the script file server side but for client side caching to work, these parts should have different and static addresses.
I wrote an ASP.NET handler some time ago that combines, compresses/minifies, gzips, and caches the raw CSS and Javascript source code files on demand. To bring in three CSS files, for example, it would look like this in the markup...
<link rel="stylesheet" type="text/css"
href="/getcss.axd?files=main;theme2;contact" />
The getcss.axd handler reads in the query string and determines which files it needs to read in and minify (in this case, it would look for files called main.css, theme2.css, and contact.css). When it's done reading in the file and compressing it, it stores the big minified string in server-side cache (RAM) for a few hours. It always looks in cache first so that on subsequent requests it does not have to re-compress.
I love this solution because...
It reduces the number of requests as much as possible
No additional steps are required for deployment
It is very easy to maintain
Only down-side is that all the style/script code will eventually be stored within server memory. But RAM is so cheap nowadays that it is not as big of a deal as it used to be.
Also, one thing worth mentioning, make sure that the query string is not succeptible to any harmful path manipulation (only allow A-Z and 0-9).
What you are talking about is called minification.
There are many libraries and helpers for different platforms and languages to help with this. As you did not post what you are using, I can't really point you towards something more relevant to yourself.
Here is one project on google code - minify.
Here is an example of a .NET Http handler that does all of this on the fly.
When dealing with websites with large amount of javascript, i see that these are still usually served to the client as one large javascript file.
In the development phase, are the javascript files usually split up (say there are >300 lines of js) to make things abit more manageable, and then merged when the website is 'put live'? Or do the developers just put up with working in one long large file?
We place different modules/classes/parts in separate files and use a proper build process to
validate the code using eg. jslint
concatenate
instrument (replace, wrap etc)
minify
An example of how to use Ant for this can be found in one of my projects here
http://github.com/oyvindkinsey/easyXDM/blob/master/build.xml.
I also have projects where the webserver automatically merges the files, localizes and then minifies them before serving the client.
So stick with whats manageable, using separate files, but do remember that if you use error reporting then the line numbers will point to the concatenated version.
In my experience — having separate files in development is the norm. It certainly makes life easier when you need to hunt for code or have multiple people working on different parts of the system.
It would be ideal to have multiple javascript files depending on the class and functionality (like you have them for java project ) in development environment.
However when you are deploying the js file in production, you should concatenate all js file in a single file and have them referred by your web application. That will make thing easy
Note: It would also be advisable to use javascript compressor to reduce the actual size and hence saving bandwidth.
Developement differs from company to company and from developer team to developer team.
I for myself am used to the approach of implementing functionality step by step, storing those functionalities in seperate files and merging everything together in most cases - at lease when i am not the only one working on a given project.