Digital Access Made Easy Steve Lee's OpenDirective blog

Is svelte.js the user-friendly developer framework?

Svelte provides an excellent Developer Experience (DX) whilst supporting a slick User Experience (UX), even on low powered devices. It does this through performing as much work as possible at build-time resulting in tight minimal code that when deployed directly interacts with the web platform in the browser.

In my last post on hyperapp I explained my interest in terms of avoiding user frustration with poor website performance, often due to heavy reliance on a lot of javascript. Hyperapp is a tiny payload and is reasonably fast so can deliver a good UX on many older devices and even with poor connectivity as is often experienced by mobile users.

In this post we look at Svelte which also provides excellent UX performance but it does this by eschewing the currently popular dev friendly runtime JavaScript VDOM techniques. Such reliance on Javascript for all rendering may negatively impact the UX on all but the best devices (which developers alone often have) but not there users. Svelte does this by using a compiler providing build-time generation of ‘laser’ precise’ UI code that acts directly with the browser DOM and BOM APIs.

Additional improvements in speed and reliability can be gained through svelte’s use of templated component markup. This transparently supports Progressive Enhancement (PE) of base coding with HTML with CSS which the browser processes with generally “fail safe” results. The developer enhances this base with additional features, usually with more fragile JavaSript behaviours according to if they are supported by the user’s device.

Whatever framework is being used, developers require a good understanding of the web platform in order to create reliable and inclusive UX that is fast. Svelte’s compiled template design providing JavaScript-in-HTML makes this a relatively natural approach to follow. This compares to the more common HTML-in-JavaScript technique (with or without JSX) which might even be said to encourage developing deep code abstractions that distance away from the platform. These might be good from a computer science viewpoint but are not necessarily a good match with the highly heterogeneous web platform. HTML and CSS have been designed with almost painful care to be as inclusive as possible and this has to be reproduced in any roll-your own code if it is not to be lost to users detriment.

In other words, svelte supports modern component UI design patterns but with a compiler reducing runtime the loading / processing times seen by users. Its also also allows developers to take direct advantage of the web platform’s strengths without requiring extra framework abstractions (such as React hooks) to be learnt. Of course, abstractions are possible but they can be added at the discretion of the developer, hopefully after a good cost/benefit tradeoff analysis from the user perspective. Svelte does have a preprocessor hook to allow extensions such as CSS tooling but I sense that keeping close to the platform is encouraged.

Svelte does provide a few abstractions of it’s own but these are minimal and extremely useful. For example Stores are an minimal approach to cross component data that. They are observable. In fact, stores very closely follow the core APIs of Functional Reactive Programming (FRP) libraries like RxJS allowing trial integration with these. Another set of abstractions make animations and transitions easier to programme. These support both Javascript and CSS approaches too, providing flexibility.

A couple of other abstractions are really overloads of existing JavaScript syntax. While this may a first seem a bad idea in practice they work REALLy well without causing any confusion and allows the source code in svelte component files to be valid JavaScript, HTML and CSS. One such syntax overload is the use of ‘export’ to declare properties exposed by components to parents. The others add reactivity in addition to the observable Stores. All assignment statements cause a redraw (hence Svelte is arguably more reactive than React and does not relay on immutability either). Mutation methods such as ‘array.push’ do not but there are simple work-arounds. Another is the use of a ‘$:’ label to mark expression statements as reactive. Reactive expressions are run before a component redraws when ever any of their dependencies change. Finally, there is a convention of starting a variable name with a $ to generate code that observes the value and also manages automatic subcription / unsubscription to stores.

One concern that might come to mind when considering the use of a compiler is the ease of debugging the output code. In actual fact, I found this to be a non problem. The code is clean and consistent using a few light abstractions that you might well develop yourself when working directly with the DOM. Even the component scope CSS is easy to work with with modern browser tooling, plus you can use global CSS as well.

Svelte is experiencing something of a major surge in interest right now and this is perfectly understandable given version 3.0 bringing together various excellent ideas, hitting a sweet spot for both DX and UK. Personally having been a heavy user of Macro Assemblers, the make tool with scripts and the awesomeness of generics using the C++ processor I fully appreciate the approach of removing work from run time in order to improve both DX and UX.

One final impressive “feature” of svelte well worth mentioning is the excellent learning resources provided by svelte’s developer Richard Harris. There’s a REPL and the tutorial provide an interactive place to explore which once completed leaves you with a solid understanding of svelte.

Svelte is relatively young but with a well led and fairly small community. Even so, it is poised to have a big impact. In fact, I just saw it prominently featured in the ‘State of JavaScript’ survey results, taking pride of place next to the big popular frameworks. Watch this space!

I explored much of svelte by developing an inclusive random number “spinner” app as a fairly non-trivial sample. This might be useful as an example, in addition to the many other resources linked to from the svelte website. Svelte has a related project, sapper, which adds features required in a SPA and server side rendering with hydration of the frontend.

Recently, Jason Lengstorf learnt svelte with Richard Harris a process that’s fun and informative to watch.

Hyperapp, the frontend web framework your users might appreciate

Hyperapp is a framework for building web interfaces and ideal for when you don't want a full-blow framework (and perhaps for when you do).

[UPDATE 2019/08/07: Added example]

[UPDATE 2019/09/06: Added link to Cypress explorer]

Right now is a “fascinating” time to be a frontend web developer. There’s plenty of interesting tools and frameworks to help ease the developer experience while providing rich user experiences. The downside can be the steep developer learning curve with complex configurations.

But your users may not always be happy with their experience of your development stack choice. The main popular frameworks, React, Vue and Angular, make heavy use of JavaScript running in the browser. Large JavaScript payloads need to be transmitted, loaded and parsed by the browser before they even start to do anything the user can see or interact with. Any errors are usually fatal, unlike errors that occur in processing declarative HTML and CSS.

This can frustrate users who experience delays, broken we sites and browser crashes. Worse, this is most likely to happen if they have old or low specification hardware, old web browsers or poor connectivity. Unless the developers are lucky enough to be targeting a controlled homogeneous environment, like an intranet, then at least some of the users are very likely to bfe in this unhappy group. They are also unlikely to remain users for long.

More recent developer tooling address some of these issues through techniques that preload some HTML or reduce the size of Javascript. For example, “server side rendering”, “code splitting” and “tree shaking” are common practice. One recent framework, Svelte, reduces runtime size by doing as much work as possible at build time.

However, there is another developer approach to avoiding user frustration. That is to not have a framework at all. Or else, use one with a very small runtime. Remember, frameworks are usually designed to cover as wide a range of requirements as possible, many of which may be irrelevent to the current project. They also often address the problems experienced by large teams working on very large websites. Thus, they may not be the best solution for you current project, even if you already know a specific framework really well.

Often a project requirements fir interaction are mostly met by browser links and forms, or perhaps a custom control or two. Sometimes only part of the site needs to be dynamically updated rather then creating the entire page with JavaScript. In these cases a full framework can be overhead and it’s feasible to just code to the DOM. That’s the approach I took with a recent project YouTube Current Time that shows the playing time of a video while you scroll around a page. Using a framework would have been overkill and introduce more dependencies and complications than necessary.

With this no-framework approach it’s usual to develop architectural patterns and structures that are effectively a custom framework that closely fit the project requirements, and no more. In fact, it is common to develop a minimal reusable starter framework that matches developer preferences and best practices. And this is where hyperapp is useful as a foundation. Especially when a functional programming approach based on the elm architecture is preferred.

Version 2 of the tiny Hyperapp framework has almost landed; it’s on master in github but the npm package has not yet been published. While the docs are not quite available yet the source code is small and relatively easy to digest. Of the 500 odd lines of source code, the first 400 are taken up with the Virtual DOM implementation and can be ignored if you want to concentrate on the framework proper. There is also a set of official examples, plus an implementation of the 7GUIs sample apps.

Here’s an overview of the few elements that make up Hyperapp. They are mostly just functions as you’d expect in a functional programming framework. Here is a simple counter app example example app, also show at the end of this post.

<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module">
      import { h, app } from "https://unpkg.com/hyperapp"

      app({
        init: 0,
        view: state =>
          h("div", {}, [
            h("h1", {}, state),
            h("button", { onClick: state => state - 1 }, "-"),
            h("button", { onClick: state => state + 1 }, "+")
          ]),
        node: document.getElementById("app")
      })
    </script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

App

The entry function that mounts and manages a DOM tree in the given DOM node. Is is passed: initial state, view and optional subscriptions and renders the view passing the state. User and other events are passed to Actions which may update the state or invoke an effect. Changes in state cause the view to be rerendered. It is possible to mount multiple apps if required.

State

There is a single state tree for the entire app and it is only ever mutated in Actions, never directly.

VDOM

Hyperapp includes its own Virtual DOM. As usual, this allows the view to describe the entire DOM tree using lightweight virtual DOM nodes. The VDOM ensure only the virtual nodes that have changed are then updated in the actual DOM.

View

Maps the State to DOM indirectly by using the VDOM h() function to build a virtual DOM tree. Abstractions can be used instead of h(), including hyperapp/html (or equivalent) helper functions for each HTML element, the JSX build time parsed HTML-like syntax or hyperx ES6 template strings parsed at run time.

Tuples

Hyperapp uses 2-tuples consisting of a function and a parameter. As JavaScript doesn’t have tuples, arrays of 2 elements are used.

Actions

Actions are functions that are invoked by the framework and passed the State and an optional parameter. They can return a new State or else invoke an Effect and return it’s resulting tuple. They are declared to the framework either as DOM node event handlers in the View or in Subscriptions passed to the App. They abstract DOM event handlers with the framework adding and removing handlers and subscriptions as required.

References to an Action can be declared as the function itself (name or inline) or a Tuple containing the function and an argument.

Effects (fx)

Effects are functions that perform side effects for the App. They can be thought of as “drivers” that perform all the external work such as calling a RESTful API endpoint, giving focus to an element or saving data to local storage. This way, Actions remain pure functions which simplifies testing and reasoning about logic.

Effects are invoked from Actions when they return a Tuple of the effect to perform as a function and an argument. Effects can invoke an Action asynchronously later.

The module hyperapp-fx contains many useful Effects.

Subscriptions

Subscriptions alow Actions to be called in response to external events that are not tied to a DOM node in the view. For example, global DOM events or even side effects such as timers. A Subscription is a Tuple of a function to set up the subscription and a props object passed as a parameter to the function. The setup function is also passed a dispatch function that it uses to ‘send’ the event to hypeapp. In addition, the setup function returns the function that hyperapp can call to teardown the subscription when it is no longer needed.

The array of Subscriptions is passed to the App by a function which is called whenever the State changes. This function is passed the State and returns an array of subscriptions. If subscriptions appear in the array, they are setup and if they are removed they are torn down. Thus, Subscriptions can vary depending on the State.

This may seem a little complex so see the Clock example which uses hyperapp/time ‘interval’ effect.

Asyncronicity

As Actions remain pure they cannot use promises or async but these features can always be used in Effects. Effects and Subscriptions effectively use callbacks for handing async events back to the framework. Any logic that manages timing or ordering of events is thus best handled in Effects, though you can modify subscriptions based on State.

Conclusion

And that’s it. Hyperapp’s few concepts and the tiny runtime make it a flexible framework, suitable for small to medium applications. The universal use of pure functions with side effects separated out also makes unit, business logic and integration testing managable. The use of Mocks and Stubs are confined to the Effects, making life much simpler. Finally, hyperapp provides a minimal foundation for building on further abstractions and patterns that perfectly model the current project domain.

Try the examples and have a play. You only need an editor, a browser and possibly a local server (eg npx serve). Just like the “good old days” of web development. Try this…

<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module">
      import { h, app } from "https://unpkg.com/hyperapp"

      app({
        init: 0,
        view: state =>
          h("div", {}, [
            h("h1", {}, state),
            h("button", { onClick: state => state - 1 }, "-"),
            h("button", { onClick: state => state + 1 }, "+")
          ]),
        node: document.getElementById("app")
      })
    </script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

Exploring with Cypress

The cypress test platform makes an ideal tool for exploring code that runs in a browser. This hyperapp explorer lets you play with the code and expands on the API description here.

React, JAMstack and React Static

A simpler development experience, deployment and fast UX with React, JAMstack and React Static.

When developing AlwaysInMind I made the concious decision to use React but avoided the more sophisticated and opinionated Nextjs. I generally feel it is better to use minimal dependencies and develop your own abstractions according to the problem at hand. This is especially true when you are learning both the technology and the application architecture as you explore your problem domain. I find this working “bottom up” approach to be much more productive and less frustrating than starting with a highly opinionated framework such as Angular. YMMV :)

I finally decided on Create React App (CRA) as providing a good starting point that neatly manages the dev and build configuration yet allows much flexibility in architectural style. This proved to be an excellent choice as I was able to concentrate on my application artefacts without CRA getting in the way.

AlwaysInMind evolved into a rich React SPA coupled with a NodeJS + Ziet micro powered API server that provides a facade to various 3rd party SaaS APIs including Auth0, Google Photos and YouTube. This is a minor variation of the so called ‘JAMstack’ architecture which in many cases provides an excellent developer experience and scalability.

In the JAMstack, HTML artefacts are created at build time, deployed to cheap static hosting, and Javascript provides enhanced behaviour including calls to HTTP APIs. This compares very favourably to the complex DevOps configuration and tighter client / server run time coupling of SSR solutions like NextJS. The React rendering can be performed at build time on the dev machine or on hosting rather than at run time on the server. JAMstack also provides a measure of Progressive Enhancement as a static HTML file is served and can enhanced Javascript behaviour, including React components. This provides a way for features such as user specific content displayed on a static ‘template’ that can be found search engines (good for SEO).

Recently, NextJS added a static export option that can provide a JAMstack like architecture. But to be honest it is backwards in approach. It takes a full SRR design and scans all the links in an attempt to determine a correct set of static files. That is pretty fragile and anyway, it is a post process to designing in an environment that is all about SSR and so likely to lead to decisions that don’t map well.

Two features stand out when analysing what Next offers when exporting to static. The first is the ability to put SPA page components in a folder and have routes automatically provided. This is minor but still useful convenience and in fact it’s fairly common to want explicitly declared dynamic child routes of an automatically mapped page.

The other useful feature is the provision of a consistent model for asynchronous data fetching in pages using getInitialProps(). Actually, a JAMStack app is likely to collect data from many sources. More importantly, some of the data can be determined at build time, not left till run time. This could be static data or data fetched from a remote service.

While these features are relatively easy to develop I recently discovered the light weight React Static framework. This has a nice clean approach to data provision, separating out the build time determined data into a single configuration file and injecting it page properties. Doing this helps clarify thinking about where and when data is captured, leading to a better UX. As for pages, they can be automatically or explicitly routed as required.

With a few Core Concepts, React Static has very few opinions on top of basic ReactJS. The source code is clean which is an advantage for such young, sole-developer project. Having said that, Tanner Linsley, the developer, is friendly and responsive.

I’m looking forward to exploring React Static for my new project. So far so good.

Cognitive Accessibility WAI Pages Mockup

The Cognitive Accesibility Task Force (TF) explore mockups of new introductory pages on the WAI website.

The W3C Cognitive Accessibility Task Force have captured a mass of knowledge and experience on the cognitive requirments and barriers that people often experience when using web tchnology. This appears in several published W3C Technical Recommendations (TRs), unpublished Editors Drafts and a set of Issues on GitHub. There is also the team wiki. Most of these documents are large, with much detail.

For many, this mass of information is dense and a little hard to digest. Examples of people looking to learn from these documents include; those new to coga concepts, developers looking for design guidance or specification authors working to support more coga requirements.

The Task Force members therefore felt a desire to provide easier access in the form of introductory signposting and way-marking pages.

The relatively new WAI Website is designed to provide easy access to the broad WAI guidance and resources. It does an excellent job of this and so makes an ideal place to put any new coga pages. These new introductory pages can then link to the published TR documents, providing selected paths into the large coga content set.

Thus, my 1st contribution as a W3C staff member is a crude mockup of how a set of pages could look when added to the WAI website. These pages are a real hack but do show the structure along with enough content to make the conepts clearer.

Here are the mockup pages

As always, the coga TF would welcome thoughts and ideas from new members.

Cognitive Accessibility with W3C WAI

How time flies! Already 3 weeks into my new role as Cognitive Accessibility Specialist.

Back in August I spotted Shadi’s announcement looking for a Cognitive Accessibility Specialist to join the W3C WAI staff. Having been involved with the work of the Cognitive Accessibility and Learning Disabilities Task Force I had become aware of the many complexities in supporting people with these “hidden disabilities” in the W3C Web Content Accessibility Guidelines (WCAG) and beyond.

The job of clearly describing cognitive preferences and then formulating suitable conformance measurements for WCAG is complex and nuanced. Cognitive requirements are often less easy to relate to than say those for visually impaired people. They commonly vary widely between individuals in both degree and combination. Defining such variable user requirements and mapping them to distinctly measurable technical features is difficult. It is also an immature science with little published research or practical experience available. Despite this, Lisa and the Task Force have done an amazing job and generated several comprehensive documents. But, there is still so much more to do before everyone who uses WCAG to inform their design and development activities will be usefully addressing cognitive preferences.

So I decided to email Shadi and Judy at the WAI, thanking them for the decision to dedicate core staff resource to help support this important work. Strangely, as I typed, I found myself realising I’d love to be “that person”. I saw a clear opportunity to widely help improve people’s experience of technology, via the standards that are used by companies, governments and others to ensure accessibility of their websites and other user facing technologies. For me, this is a change in approach from developing a cognitive AT product, AlwaysInMind, but possibly more suited to my skills and background.

Long story short, I ended up applying for the post and after various bumps in the road (including the unwelcome uncertainties caused by the looming BREXIT) I have now just finished my 3rd week as part of the W3C WAI team, employed by ERCIM in France. The exact details of my role will emerge in time but in essence I’ll be working to improve the coga11y story. This will involve fairly horizontal activity around coga, WCAG, Personalisation and the EU 2020 Easy Reading project of which W3C WAI are consortium members.

My 1st experience was incredible! While the ink was still wet on the contract, I rushed over to the annual W3C TPAC meeting in Lyon, France. In 5 days I managed to meet many of the dedicated folks working on WAI standards and guidelines through their activity in workgroups and taskforces. A handful were old friends, some going back to the time I started serious accessibility work on GNOME, Mozilla Firefox and the IAccessible2 platform API for Windows. Many others, I have met since, either on line or at various conferences. A few I have followed and respected from a distance until getting the chance to meet them at TPAC. Such an inspiring group.

I found myself playing WAI “Bingo” and managed to get a full house of the various accessibility groups; AG, APA, EO, ARIA, Coga, Personalisation, ACT and others. It was a whirlwind of meeting welcoming people while absorbing organisational and procedural details of W3C and WAI. Phew!

The next 2 weeks back home have been and intense but enjoyable period of on-boarding. The usual medley of meeting people, attending working group meetings, learning my way around the intranet, plus installing and configuring tools.

Perhaps most important has been becoming familiar with the relevant publications. There’s only around 10 key documents to internalise but considering WCAG is not alone in it’s size and density I’m going to be very busy over the next 3 weeks! :)

I’m so happy to be a part of WAI and very much look forward to contributing to the Coga11y support of WCAG and wider.