DEV Community

Discussion on: Bringing Order to Web Design Chaos (with Web Components)

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?

thatjoemoore profile image
Joseph Moore Author

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.

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.

jaywolters profile image
Jay Wolters • Edited on

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 Author

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.