Scripting

Introduction

Client-side scripting languages like JavaScript can add attractive features to websites. But scripting is usually not required, wastes bandwidth and makes websites unusable for some users.

General Recommended Practice

6.5% of users are reported [1] not to have support for JavaScript, which is the most popular and widely supported client-side scripting language. The proportion of unsupported users is likely to be higher in the developing world. Therefore, in general, we recommend avoiding the use of client-side scripting such as JavaScript wherever possible, e.g. where the effect can be replicated without the use of client-side script. In cases where this is not possible, it is important to ensure that the site is still usable without browser scripting support. This maximises the likelihood that users will be able to access your website, whatever browser they have. It will also help keep the site usable by users who have disabled JavaScript on their browser, users on mobile devices, and disabled users who are using assistive technology.

Some commonly scripted features such as navigation or menu rollovers have obvious HTML or CSS equivalents — browser support for CSS is more widespread than that for document manipulation using scripting. Other seemingly useful scripts can also be rendered unnecessary, e.g. scripts that choose a browser-specific CSS file are not needed if you instead write a single CSS file that is compatible with all browsers.

Sometimes scripts can be used to add optional functionality to a site, such as validation of user input. In this case, scripts should be hidden from users without scripting support, as described below, and the site should be tested without JavaScript enabled, to ensure that it is still fully usable.

If you find that client-side scripts are necessary for your site, or you are working with an existing site containing lots of scripts, the following recommendations should help keep your site as usable as possible.

Script Management, Loading and Caching

Script locations

Scripts included at the top of a page will delay anything below the script from rendering or downloading. Therefore, in general it is best practice to place scripts as far down the page as possible.

For scripts that don't have any output, such as libraries of function definitions, it is possible to tell the browser to load the scripts after the rest of the page by using the defer attribute of the script element, e.g.

<script type="text/javascript" src="/scripts/library.js" defer="defer" />

However, browsers don't always implement defer correctly. Firefox still blocks page rendering and downloading of further content until the scripts are downloaded, while Internet Explorer still downloads the script, potentially holding up other data. If a script is not required until after the rest of the page content has downloaded, include it at the end of the page rather than using defer.

In order to use HTTP compression to compress scripts reliably it is necessary to include them in the HEAD of a document, as most browsers only implement script compression in the HEAD. However, this will result in rendering and downloads for the entire page being delayed. Given this, combined with the fact that some older browsers have problems with compressed JavaScript, we recommend that script files are not compressed, and are included as far down the page as possible rather than in the HEAD. It is possible to reduce the size of script files without compression, using a text filter such as JSMIN as described below.

Multiple Script Files

The fewer the number of script files the user has to download, the fewer HTTP requests need to be made, cutting down the bandwidth overhead. This suggests that combining code into a single script is a good idea — and in fact it is when scripts will always or almost always be loaded together, e.g. when they contain related functionality or when browser-specific versions of JavaScript files have been written as separate files. Combining scripts also takes advantage of the default settings in Internet Explorer and Firefox to download a maximum of two files at the same time from a site — using fewer files will take up fewer download slots.

The disadvantage of this approach is that it potentially forces the user to download a lot of script at once. This could considerably delay access to the front page of a site, assuming that is where the script is placed. Browsers will not finish loading page content until they have downloaded and executed script files, even if in theory they can download multiple files at once, so a large script could in some cases significantly slow down access to a site's content.

A good compromise is to separate the script files into a few logically distinct areas so that, depending on the route the user takes through the site, they will only load as much script as is necessary. Each page need then only contain the script required for its own functionality. Provided that you do not break any dependencies, you can reorganise your scripts at will. You must simply ensure that all functions that will be called, and all functions that they depend on, are defined.

It is generally better to separate out script from HTML where possible, in order to improve the effect of caching. If a page changes and the script stays the same, the whole of the code need not be downloaded again. However, if a script is so small that it is not worth the additional overhead of making another HTTP request, it may be worth considering leaving it inline.

Separate dynamically generated and static script into different files. This will allow static code to be cached and shared between pages.

Ensure that each script is loaded only once in a page — multiple includes can creep in over time as the numbers of scripts and pages grow. Even if caching is enabled, meaning that the file will not actually be downloaded each time, each instance of the script must be executed on the client machine before the rest of the page displays.

How to Write your Scripts

Text Filters for Script Files

JavaScript and VBScript files can be shortened considerably by passing them through text filters that create a shorter file through techniques such as reducing white space, removing line breaks, and using shorter variable and function names. This process often results in script files that are difficult to read, and the process is usually one-way, so it is worth remembering to keep an original copy of script files for future changes or debugging.

  • JSMin[2] by Douglas Crockford, a JavaScript filter;
  • ESC[3] by Saltstorm, configurable, works with various scripting hosts;
  • JSLint[4] by Douglas Crockford, JavaScript validator, useful to check code is correct before processing it, as bugs are usually very hard to spot in processed code.

Consider Users Without Script Support

You can include HTML code in the page that will only be used when scripting is not supported or is disabled, using the following method:

<noscript>
<h2>Navigation</h2>
<ul>
  <li><a href="/">Home</a></li>
  <li><a href="/news">News</a></li>
  <li><a href="/contactus">Contact Us</a></li>
</ul>
</noscript>

Hiding Script Within HTML

If you are using HTML and not XHTML, script code should always be hidden in HTML comments, to ensure that a browser that doesn't support these languages will hide the code rather than displaying it in the page:

<script type="text/vbscript"><!--
document.write("Hello World!")
'--></script>

<script type="text/javascript"><!--
document.open();
document.write("Hello World");
document.close();
//--></script>

The syntax on the last line of each script, where the closing HTML comment is preceded by a comment in the scripting language (e.g. '), ensures that the browser does not try to execute -- or --> as code, which can cause some browsers to display an error message.

Script within XHTML

If you use XHTML, you should not place your script in comments because XHTML processors are legally allowed to remove or ignore them. Also, in XHTML, the characters <</tt> and & are not permitted in embedded scripts (inside script elements).

One way to to keep your XHTML valid is to rewrite your embedded scripts like this:

  • Replace x <= y with y => x
  • Replace x && y with !(!x || !y)

Alternatively, you may find it easiest to place all JavaScript and VBScript in external files.

You could instead place your script inside a CDATA block, but older non-XHTML browsers will not understand this and will probably generate errors or refuse to process the script.

AJAX

AJAX (Asynchronous JavaScript and XML) is a combination of client side and server side scripting. It uses JavaScript on the client to make XML requests for additional data to a program on the server, without reloading the current page. AJAX makes it easier to write client side scripts to request information from the server. It also reduces the need to download entire pages from the server.

AJAX is a relatively new technology, currently associated with larger interactive sites that are designed primarily with high-bandwidth users in mind, such as online applications. Looking to the future it is possible that AJAX could also be used on low-bandwidth sites to minimise the data transfer necessary between the client and the server.

Summary

  • Avoid using scripts wherever possible
  • Include scripts as far down the page as possible
  • Separate script files, so that script is only loaded as needed by a user's actions
  • Filter script using tools like JSMin[2] to reduce file sizes

Footnotes

[#1] http://www.upsdell.com/BrowserNews/stat_trends.htm

[#2] http://www.crockford.com/javascript/jsmin.html

[#3] http://www.saltstorm.net/depo/esc/

[#4] http://www.jslint.com/lint.html