ApiaryActive
Try: pause · settings · learn · wipe
← Community / Reading Room
DF
dev-patterns · 3 min read

dev fallback graceful degradation

As a developer, you've likely encountered situations where your carefully crafted code is rendered useless by a user's browser or environment limitations.…

As a developer, you've likely encountered situations where your carefully crafted code is rendered useless by a user's browser or environment limitations. It's as if the world outside Apiary has its own set of rules and constraints, leaving us to adapt and overcome.

In this lesson, we'll explore a technique that will help you write more resilient code: dev fallback graceful degradation. This approach ensures your application remains functional even when fancy APIs or features are unavailable, making it a valuable addition to any developer's toolkit.

The Technique

At its core, dev fallback is about anticipating potential failures and providing an alternative path forward. It involves three key components:

  1. Feature detection: Identify the specific feature or API being used and determine if it's available in the current environment.
  2. Polyfill (optional): If the feature is missing, provide a polyfill to enable basic functionality. This can be a custom implementation or a third-party library.
  3. Fallback UI: Design an alternate user interface that still provides value, even when the desired API or feature is unavailable.

By combining these elements, you create a robust system that degrades gracefully in the face of uncertainty.

Example 1: Using Web Storage

Let's say your application relies on web storage to store session data. However, older browsers may not support this feature. In this case:

function getSessionData() {
  if ('sessionStorage' in window) {
    // Modern browser, use web storage
    return sessionStorage.getItem('data');
  } else {
    // Fallback: use a cookie or local storage alternative
    const data = localStorage.getItem('data');
    return data || '{}';
  }
}

In this example, we first check if the sessionStorage property is available. If it is, we proceed with web storage. Otherwise, we fall back to using local storage.

Example 2: Using Fetch API

Imagine your application relies on the Fetch API for making HTTP requests. However, some older browsers may not support this feature:

function makeRequest(url) {
  if (window.fetch) {
    // Modern browser, use fetch API
    return fetch(url)
      .then(response => response.json())
      .catch(error => console.error('Fetch error:', error));
  } else {
    // Fallback: use XMLHttpRequest or a library like Axios
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onload = () => {
      if (xhr.status === 200) {
        console.log(JSON.parse(xhr.responseText));
      }
    };
    xhr.send();
  }
}

Here, we check for the presence of the fetch function. If it's available, we proceed with the Fetch API. Otherwise, we fall back to using XMLHttpRequest.

Example 3: Using Web Font Support

Suppose your application relies on web fonts for its typography. However, older browsers may not support this feature:

function loadWebFonts() {
  if ('FontFace' in window) {
    // Modern browser, use @font-face rule
    const font = new FontFace('Open Sans', 'url(https://example.com/open-sans.ttf)');
    document.fonts.load(font);
  } else {
    // Fallback: use a generic font or a library like WebFont Loader
    document.body.style.fontFamily = 'Arial, sans-serif';
  }
}

In this example, we check for the presence of the FontFace property. If it's available, we proceed with loading the web font using the @font-face rule. Otherwise, we fall back to using a generic font.

When NOT to Use Dev Fallback

While dev fallback is a powerful technique, there are situations where it may not be necessary or desirable:

  • When dealing with critical security features, such as encryption or authentication mechanisms.
  • In cases where the feature or API is essential for core functionality and cannot be replicated through alternative means.

Related Apiary Lessons

  • Feature detection: Learn how to detect specific browser features and adjust your code accordingly.
  • Polyfills and shims: Discover how to create custom polyfills and shims to enable basic functionality in older browsers.
  • Progressive enhancement: Understand the importance of progressive enhancement and how it relates to dev fallback.

Conclusion

Dev fallback is a vital technique for writing robust and resilient code. By anticipating potential failures and providing an alternative path forward, you can ensure your application remains functional even when fancy APIs or features are unavailable. Remember to balance feature detection, polyfills (if necessary), and fallback UI design to create a gentle degradation experience.

As the great Apiarian philosopher once said: "A bee's strength lies not in its wings, but in its ability to adapt to changing winds."

Frequently asked
What is dev fallback graceful degradation about?
As a developer, you've likely encountered situations where your carefully crafted code is rendered useless by a user's browser or environment limitations.…
References & sources
  1. Apiary Reading RoomOpen, cited knowledge base — funded to keep bee & practical research free.
From the Apiary Reading Room. Opinion & editorial — not financial advice. We don't overclaim.
More from the Reading Room