milliseconds Add up in the Browser

dojo’s dynamic inclusion of the logic required to render pages is great. The line dojo.require("widget"), ensures that the code required to run “widget” will be ready to run.

There is a hidden cost to this - the underlying logic and requests to get the code from the server.

On a complex page that has a lot of widgets (more than 50% of the dijit widgets offered), it is worth considering the following tags:


<script type="text/javascript" src="dojo/dijit/dijit.js"></script>
<script type="text/javascript" src="dojo/dijit/dijit-all.js"></script>

Although dijit-all is large, it is compressed, and it has all the widgets. A single request can replace 50 or more requests. Each request has an overhead of about 15ms, even if the javascript is cached in the browser. It is definitely worth running a test with Firebug to see if you can realize any performance gains with this strategy.

The ideal solution is a custom build, but you can’t always solve problems the “best” way. Sourcing dijit.js and dijit-all.js, using a loading .gif, and configuring caching carefully reduced page load time to 1/3 of the initial value, and provided a more graceful load process.

dojo dijit Tri-State Checkbox Widget

The link above is a demonstration of a dojo dijit Tri-State Checkbox Widget. It includes a nice button interface to test the properties, methods, and events of the widget, some documentation, and a link so you can download the widget and the test code.

It has been integrated into a complex application and is working well.

Interesting notes on this widget:

  • Spent time exploring how to indicate an indeterminate state for a checkbox. The de facto standard is a small box within the box, so that is what is implemented.
  • Widget is actually a text input that can contain the values on, off, or indeterminate.
  • Used a blank.gif to create the space in the focus node.
  • Value can be set by using a boolean (true=on, false=off), number (0=off, 1=on, 2=indeterminate), or string (off,on,indeterminate)
  • Checked maps to on, unchecked is considered off
  • Value is sent to the server regardless of input state. This is different than a traditional checkbox, where the value is only sent if the checkbox is checked.
  • Tried to avoid duplicating effort, used inheritance as much as possible.
  • Realized that even a ’simple’ widget involves significant complexity, and thorough testing is important prior to integration into pages.
  • Discovered that building a widget for dojo 1 does not build a widget for 0.9 - had to build a second copy for 0.9 to integrate into an older application.
  • Appreciated the dojo / dijit architecture, it made adding the widget a nice, efficient process.

PHP Session Development Strategies

  • Use Firebug to get the session id off the page requests.
  • Find the directory session files are stored in. On busy, shared servers, this is often /tmp. Check /etc/php.ini or possibly /etc/httpd/conf.d/php.conf.
  • To simulate a session timeout on the server side, delete the session file.
  • To simulate a cookie timeout on the client side, delete all private data (FF) or cookies (IE).
  • To simulate a lost connection - disconnect or disable the network connection.
  • Use more to view the contents of a session file.
  • Use session files to reduce the amount of logic required for execution. You can assume the session file must be read for authentication, therefore, adding a few more bytes in to reduce execution time should yield a performance gain. Be careful to only store data which is valuable for enough operations that the storage increase is warranted.
  • ACL can be stored in session files. It may be faster than using a database.
  • Never store passwords in session data.
  • Language in use is good for storage in session files.
  • Session files must not be accessible through the web. Should only be accessible for appropriate users.

Generated profile.js for dojo Builds

To generate a profile.js file for dojo builds, you can use the following command string:

grep dojo.require * | sed “s/dojo\.require\ *(\ *\([\’\"][^\)]*\)).*/\1/” | awk ‘{l=length($0);if (FNR!=1) printf “\n,%s",$0; else printf “%s",$0;}’ > middle

Sample output:

"dojo.parser"
,"dijit.layout.ContentPane"
,"dijit.layout.TabContainer"
,"dijit.form.Button"
,"dijit.ColorPalette"

If this ouput is prefixed with (name the file top):

dependencies ={
    layers:  [
        {
        name: "mydojo.js",
        dependencies: [

and postfixed with (name the file bottom):

        ]
        }
    ],
    prefixes: [
        [ "dijit", "../dijit" ],
        [ "dojox", "../dojox" ]
    ]
};

It will yield a properly formatted profile.js file.

Use cat to assemble it, like so:

cat top middle bottom

Note that dojo.parser and other core elements don’t have to be specified, but it is simpler to leave them in.

Craching

Crache - Poorly configured server caching which prevents distribution of updated files such as CSS, images, and javascript. Crached pages display poorly until the browser cache is cleared.

*** This can be a very subtle problem, as developers often clear the browser cache by force of habit. They would not notice the problem. Site visitors that return to your site after updates may be presented with pages that do not display or function properly.

Key resources

(Apache)

http://httpd.apache.org/docs/2.2/caching.html
http://httpd.apache.org/docs/2.2/mod/mod_expires.html
http://httpd.apache.org/docs/2.2/mod/core.html#fileetag
http://httpd.apache.org/docs/2.2/mod/mod_cache.html

(Mozilla Firebug and YSlow)

https://addons.mozilla.org/en-US/firefox/addon/1843
https://addons.mozilla.org/en-US/firefox/addon/5369