Monday, March 03, 2014

Single page apps with better than HTML5 storage using MFlow

See this article without the extra newlines introduced automatically by  blogger

In the latest version of MFlow, the autorefreshed widgets (the ones that use autRefresh, appendUpdate and prependUpdate) can be cached. The advantage is that there are no spurious round-trips to the server to get fragments of pages  that already have been sent. 

The goal is to avoid to  access the server except whenever a heavy front-end framework would have the need to do it: when there are something new to get from the server.

While JavaScript frameworks rely on heavy Javascript programming using the lattest HTML5 API storage facilities, MFlow relies on  HTML fragments, retrieved using GET queries. They are stored in the browser HTTP cache.  The HTTP caching  works for you, The amount of programming is reduced drastically in relation with JavaScript frameworks. and the effect is compatible with all browsers.

See for example this  piece:

 showProducts= autoRefresh $
do  absLink IPad << b "See Ipad models"
            showModel IPad
<|> do  absLink IPod << b "See Ipad models"
            showModel IPod

Shows initially two links to two products. Since it is autoRefreshed, the fragment refresh itself when one of the links is pressed. When the user press the first of the links, by the definition of the Monad instance (see this) the code that follows it is executed, so the rendering of the model appears. 

When the other link is pressed, the rendering of the second model appears, and the first collapses. (see the links section of the wiki) .  

When the first link is pressed again, since the former was a GET request, if it is cached by the appropriate directives, there will not be a call again to the server. The fragment will be read from the browser's HTTP cache.

That is how  MFlow can perform the caching that the Javascript frameworks do with heavy HTML5 API programming

MFlow has the setHttpHeader  call that, as the name tells, set the HTTP header directives. 

setHttpHeader :: MonadState (MFlowState view) m
            => ByteString -- ^ name
           -> ByteString -- ^ value
           -> m ()

It is session-wide, so if you can put it at the beginning of the session. You can change it afterwards whereever you like. 

For example, this site now has a directive:

       setHttpHeader "Cache-Control" "public, max-age=300"
This caching permits the options on the cascade menu on the demo to be filled without invoking repeated roundtrips to the server.

More fine control on HTTP caching will be developed. A component-based framework like this can mix pieces with different inherent caching needs: A widget that show private information inside a general container widget with less restrictive policy must respect the more restrictive directive automatically.