Frontal - a new approach to triggering Javascript behaviour

My friend Carl has just released a really interesting Javascript library called Frontal. I've had a night to sleep on it and thought I'd share my thoughts.

The key problem Frontal addresses is 'some Javascript needs to be run only on some pages'. There are a few different approaches to this:

Per-page scripts

The first approach is to have lots of Javascripts that only apply for the current page, and insert them in the HEAD of the document:

<head>
  <script src="base.js"></script>
  <script src="something-page-specific.js"></script>
</head>

Pros:

  • You can attach your scripts modularly
  • No inline scripts

Cons:

  • Lots of JS files to keep track of
  • Lots of HTTP requests to your server
  • Each page's JS isn't precached
  • No way of passing parameters to the script, everything has to be hard-coded

Inline triggers

A second approach is to have some base library but then activate with some inline script in your page:

<head>
  <script src="base.js"></script>
  [...]
</head>
<body>
  [...]
  <script>
    doSomeBehaviour('foo', 'bar');
  </script>
</body>

Pros:

  • One JS that's easily cached
  • Triggered functionality per-page

Cons:

  • Mixes JS with HTML

POSH triggering

This third approach is one I've preferred to use in the past is to have the Javascript pick up elements that exist in the markup in some sort of POSH form.

<head>
  <script src="base.js"></script>
  [...]
</head>
<body>
  [...]
  <div id="foo">
    <span class="bar">An element</span>
  </div>
</body>
In this instance the base.js would pick up that there's an element with @id="foo" and do some action based on it (or rather, attach some behaviour).

Pros:

  • One JS that's easily cached
  • JS only applies when needed

Cons:

  • Lots of findById() to check every possible element that might trigger a behaviour
  • Can only apply after DOM is ready

The Frontal approach - path-based actions

What frontal does quite simply and brilliantly is allow you to specify Javascript that gets run based on the URL of the current script:

$frn('/blog', function(){
   // some blog-specific action
});

$frn('/news/latest', function(){
   // e.g. script that refreshes the list of news items
});

$frn(/blog\/.*zend.*/, function(){
   // action for blog items with Zend in the URL
});
I find this approach really interesting, and would be pretty keen to see how it can be integrated with your average framework's routing mechanism (specifically ZF and the URL view helper).

Pros:

  • One big JS
  • JS only applied on pages where it's needed

Cons:

  • Page-specific JS might not be fine-grained enough
  • Need to link to Frontal as a library to use (unless you replicate the pattern)

Looking forward

At first glance I tend to think that a mixed strategy of the Frontal and POSH approaches - I still tend to think that JS should get as much of the 'stuff' it needs to understand from POSH-esque structures within the page (e.g. a Google Map probably shouldn't have it's coordinates hardcoded in the JS). However it does get costly to keep traversing the DOM, and you can't always wait for the DOM to be available, so there's a strong argument for combining that with Frontal and nesting the POSH checking inside Frontal clauses.

I'm going to keep nagging Carl about getting this integrated into a Zend project, and would like to see it bundled into a jQuery plugin.

Bookmark and Share

Comments

1.

In nearly all sites, except for the very biggest and the very smallest, I much prefer to have several seperate js files containing code for a specific part of the website or to perform a specific task. The same preference applies to css files too.
For cacheing and http requests this is not ideal but for simplicity, and ease of maintenance I much prefer it.
In situations where a single js file is prefered I could see the value in frontal.

Jquery plugin would be a massive win.

Russell
25th March 2010, 11:25

2.

This is an interesting approach indeed, but I can see some issues..

Firstly, if you have a lot of page specific scripts, do you really want to load all of them on all pages? Not only will this increase the size of the script, it'll make parsing it slower due to size.

Secondly, when developing JS code it's a good idea to separate it into multiple files - you don't put all of your PHP into one file either.

Personally I'm in favor of using a script to automatically concatenate and cache all scripts a specific page needs into a single file.

Jani Hartikainen
25th March 2010, 12:19

3.

@Russell - is that for performance, or is it for ease of use at your end?

What I've been thinking about this morning is that somehow you could specify the which JS applies to which page somewhere within your MVC app, and then the MVC framework could compile it into one big JS with Frontal rules giving the best of both worlds.

Ciaran McNulty
25th March 2010, 12:21

4.

@Jani Organisationally in my codebase sure, the same applies to things like CSS, but if you're concatenating and caching before serving to the user, something like Frontal makes big sense.

Ciaran McNulty
25th March 2010, 12:23

5.

Yeah, for ease of use rather than performance. Then combat any performance issues caused by multiple http requests with the concatenating and caching Jani recommends.

Russell
25th March 2010, 14:00

6.

Glad to see i've inspired some debate.

When i was first thrashing out this idea my first thought was to write a jQuery plugin. But wasn't convinced that my approach followed the jQuery paradigm of finding elements and then doing stuff to them.

That said it would only take a few lines to layer on the jQuery sugar.

We've just started a fresh ZF project at work and i plan to try writing our JavaScript on top of frontal; i'll be sure to write up my findings.

Carl
25th March 2010, 19:45

Commenting is currently disabled