DEV Community

Cover image for Bringing Order to Web Design Chaos (with Web Components)

Bringing Order to Web Design Chaos (with Web Components)

Joseph Moore on February 09, 2018

Or, how I learned to stop worrying and love Web Components In my maturation as a Software Engineer, I've found that stories of the probl...
Collapse
 
rafegoldberg profile image
Rafe Goldberg

Great read, especially re: deployment and the CDN configuration! I'd love to know more about how you made all this code cross-browser compatible?

Collapse
 
thatjoemoore profile image
Joseph Moore

It's all in our loading script. Our build process for each component outputs three scripts: the main, concatenated components.js (with the ES6 version of our components), components-compat.js (run through Babel, so it's pre-ES6 compatible), and a 'bootstrap' script, which shares the name of the component (so for byu-theme-components it's byu-theme-components.js). The bootstrap script does two things: first, it feature detects support for Custom Elements and Shadow DOM and, if necessary, loads the appropriate polyfills. Once the polyfill has loaded, it feature detects ES6 class support, then either loads components.js or components-compat.js.

The goal with this bootstrap process was to remove the burden of cross-browser compatibility from the consumers of our elements. It's all hidden from them so that all they have to worry about is the compatibility of their own code, not ours.

Here are the (simplified) relevant sections from the bootstrap scripts:

var comps = window.byu.webCommunityComponents;
function needsPolyfills() {
  var forcePolyfills = comps.forcePolyfills;
  var needsPolyfills;

  //This is here because if we have multiple component bundles on the page and one of them has already loaded the
  //  polyfills, we would erroneously detect that we don't need to load them and load the native ES6 code instead
  //  (which could cause problems).  So, we set 'needsPolyfills' to tell ourselves to ignore the feature detection.
  if (!('needsPolyfills' in comps)) {
    var shadow = !!HTMLElement.prototype.attachShadow;
    var customElements = 'customElements' in window;
    needsPolyfills = comps.needsPolyfills = !shadow || !customElements;
  }
  return needsPolyfills || forcePolyfills;
}

function canDoEs6() {
  //Template strings are a good stand-in for class syntax detection
  if (!String.raw) return false;

  //And, we'll fall back to hacky IE detection, just in case.
  var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
  return !isIE11;
}

We used to detect ES6 class support directly, but that involved calling either eval or new Function('...'), both of which fell afoul of some of our sites' Content Security Policy needs. So, we decided that the presence of string template literals (String.raw) was a pretty good proxy for checking for class support.

There's a lot that can be improved about our bootstrap script (making it smaller, for one), but it's worked out pretty well for us.

Collapse
 
jaywolters profile image
Jay Wolters • Edited

I would really appreciate your views on IE11 and web components. Specifically the effort required to support that browser with poly-fills. It appears now that these components do not support IE11.

Thread Thread
 
thatjoemoore profile image
Joseph Moore

Yeah, the decision was made a while back to start dropping support for IE 11, as our usage numbers for it had dropped below 1%.

I think for most people, it's very much possible to continue supporting it. The conditional loading of polyfills is a solved problem, and we've even got it a bit more streamlined than before in the upcoming V2 of our theme components.

The biggest barrier to us supporting IE11 has been the lack of Grid Layout support. For better or for worse, the new version of our header that's being rolled out soon uses a lot of grid, and since Edge shipped grid a few versions back, the Powers That Be decided that it was time to truly break IE compatibility.

Personally, I'd like to keep maintaining some form of compatibility, even if it's just in our fallback stylesheets. Producing an ES5 bundle wasn't hard, deciding which bundle to load wasn't hard (especially since ES modules shipped everywhere but IE), but it was decided that it wasn't worth it for the small number of IE11 users we were seeing.

Our IE experience is probably atypical for most businesses. Being a university, we have three main audiences: students and prospective students, faculty and staff, and alumni. Each group is different, but for the most part, they're either using mobile devices or recent laptops running Chrome, Safari, or Edge to access our sites. The biggest group is our students, and we tend to see a 4-5 year long cycle with them. That's about how long it takes a big release, like Windows 10, to reach near-100% adoption in our student body. This is because our students tend to buy a new laptop right before their freshman year and keep it until they graduate. Our faculty and staff are mostly on a two or three year hardware refresh cycle, so they're usually running a recent OS too. So, at this point, the majority of our users are using a device that has never had IE11 as the default browser.

Like I said, I still think it wouldn't be terribly hard to keep supporting IE, but even though I did a lot of the initial work, I'm no longer involved in any of the decision-making in this area, so my opinion doesn't count for much.

Collapse
 
rafegoldberg profile image
Rafe Goldberg

Well this is awesome – I appreciate all the detail! Recently I've been dealing with some of these issues myself, so reading through your conclusions is extremely insightful.

Collapse
 
patrickcole profile image
Patrick Cole

I really enjoyed this post on WebComponents! I've been following their progress for a little while now and this is a wonderful insight to an implementation. Everything presented here is worth presenting to any development team considering using WebComponents, even the tweet about appreciating Polymer :).

Thank you Joseph for providing us with these insights on your work at BYU.

Collapse
 
equinusocio profile image
Mattia Astorino

Hi, why don’t use css custom properties?

Collapse
 
thatjoemoore profile image
Joseph Moore

In some of our components, we actually do! They can't do everything for us, though. For example, I'd love to make the setting of the mobile-to-desktop breakpoint in our header be a CSS property, but there isn't currently a way for Javascript to read that value, which we need in order to switch out our template when we move between mobile and desktop (we couldn't figure out a good pure CSS way to do it that conformed with the design we were given).

I'm really excited about CSS custom properties, but we just haven't had many opportunities to use them, as most of the components we've produced so far don't allow for much style customization.

Collapse
 
equinusocio profile image
Mattia Astorino • Edited

I understand. Anyway you can read custom property value with js from the element computed style with .getPropertyValue('--foo-bar'). Or set it with setProperty()