Editor’s note: this article is the first in a series that will focus on web development using CSS postprocessors and JavaScript transpilers.

ladage-heap-front-end-code

“All things old become new again.” – Harley King

The web has a way of getting back to its roots. Even as web standards have evolved and advanced over time, developers have created tools and techniques that push beyond the capabilities of the browser itself. Over time, the development community will often re-evaluate these tools, absorbing the good parts into the languages’ standards and best practices, and discarding the not-so-good stuff.

This cycle of technological expansion and contraction is a natural reaction to the limitations of the browser’s native functionality. Take Adobe Flash, for example. In the early 2000s, Flash dominated the web landscape whenever rich interactive experiences or streaming video were needed, only to eventually be replaced by equivalent or superior functionality in HTML5, CSS3, and JavaScript. It obviously had its shortcomings, but at the time, Flash was a necessity: it bridged a functionality gap, and ultimately, it encouraged web standards to catch up.

This phenomenon happened again more recently with the rise of responsive web design, which in essence is a return to the natural fluidity of the web after the industry’s decades-long love affair with fixed-width layouts. To paraphrase Jeremy Keith, the web was always responsive, right up until developers and designers came along and broke it. In the case of responsive design, the primary technological advancement — media queries — was actually just a small piece of the puzzle. The change that really mattered was the development community’s shifting perception of how a website should be conceptualized and built.

We believe front-end development may be on the verge of another great re-evaluation. A combination of new native CSS and JavaScript features, paired with a new crop of less obtrusive build tools, is allowing us to get back to writing the kind of pure code that attracted us to front-end development in the first place. In order for this to happen, though, front-end developers will need to rethink how they approach their development process.

Preprocessors Perpetuate the Problem (Say That Five Times Fast)

A few months ago, our team started recognizing a trend with CSS preprocessors such as SASS or LESS, JavaScript preprocessors such as CoffeeScript, and JS libraries such as jQuery. These tools fill a gap; they provide a solution to the limitations and inconsistencies found in native CSS and JavaScript. They have become very, very popular, but have also quietly pulled us further and further away from writing our code in real, standards-based CSS and JS.

A big knock against CSS and JavaScript is that the process of new feature proposal, ratification and browser implementation is often slow moving. Even after new standards are agreed upon by their governing bodies (for CSS, the World Wide Web Consortium, and for JavaScript, Ecma International), they must then be implemented by the fragmented browser market. And then, even after these standards are implemented in modern browsers, developers have to play the waiting game until unsupported browsers become obsolete (or at least use clunky polyfills to trick older browsers into supporting these new features).

CSS has always lacked certain programmatic features that allow for more efficient, reusable, and maintainable code. Preprocessors like SASS and LESS were born to extend CSS and provide conveniences like variables, functions, nesting, and inline importing. These tools added great value to the language and continue to enjoy immense popularity in the web development community.

A similar story exists within the JavaScript world, although it goes back farther in history. JavaScript is a very powerful language, but it has suffered from inconsistencies and feature support across browsers, as well as a scarcity of convenience functions for interacting with the DOM. Libraries like jQuery have addressed these concerns for years, and have embedded themselves so deeply in the web development community that jQuery and JavaScript are often (and wrongly) viewed as synonymous.

The problem with all of this is that we’ve slowly been putting more and more layers of abstraction between real front-end code and us. SASS is not CSS. It’s a separate language, with a different syntax, which must be compiled into CSS by a build tool before it can be served to the browser. These build times can get progressively longer on larger projects, especially if you’re using the notoriously slower Ruby version of SASS.

On the JavaScript front, jQuery has served as an indispensable tool, but also a crutch for developers. Many of the problems that jQuery solves do not exist in modern browsers. We’re getting to the point where libraries like this no longer have to be assumed dependencies at the start of a project (there are plenty of resources on the web to help you decide whether it’s time for you to drop your jQuery dependency).

Is it finally time to reverse direction and get back to writing real code? Our development team decided to explore this topic.

Goodbye, Preprocessors; Hello, Postprocessors and Transpilers

ladage-heap-front-end-code-2

First, let’s discuss the difference between a preprocessor and a postprocessor.

Preprocessors like SASS force you to write your code using a different language and then compile it into standard CSS. Postprocessors, in contrast, allow developers to write real, powerful, bleeding-edge CSS and then process and transform that code into output that will work in today’s browsers (or, with the change of a few configuration settings, yesterday’s or even tomorrow’s browsers). Aside from the fact that postprocessors let you write CSS code that isn’t even officially CSS yet, there’s no new syntax to learn, and you can solve many of the same problems that preprocessors also solve.

PostCSS is probably the most popular postprocessor available today. It’s written in JavaScript on the Node.js platform, and is very modular and customizable. It’s also fast; compile times are up to 40 times faster than Ruby SASS, according to its creator.

If there’s a SASS feature you can’t see yourself giving up, there’s a good chance a PostCSS plugin for it already exists. And unlike Ruby SASS, if there isn’t, you can write your own in plain JavaScript using PostCSS’s API.

JavaScript transpilers operate in much the same way as CSS postprocessors. You write native — or even next-generation — JavaScript, and then convert it to JavaScript that can be run on current browsers. Babel and Traceur are popular transpilers that convert yet-to-be-ratified ECMAScript 6 (and even ECMAScript 7) JavaScript code down to well-supported ECMAScript 5 code. This gives you the ability to write powerful JavaScript without any dependence on libraries, such as jQuery. Theoretically, this also means that we can someday “flip the off switch” on our transpiler and run the ES6/ES7 code natively in supported browsers, although we’re under no illusions that this will be a completely painless process.

Improving Processes Without Sacrificing Functionality 

Our team’s first venture into the world of postprocessors was minor, but eye opening. We put our collective baby toe in the water and swapped out Compass’s CSS3 mixins for Autoprefixer, a PostCSS plugin that adds vendor prefixes to CSS rules based on current browser usage statistics. This was a relatively easy change for us to implement on a new project. Instead of calling a SASS mixin to use a not-yet-fully-supported CSS property, we instead just wrote the CSS property as if all browsers already supported it.

This meant no memorizing prefixes, and no function calls using another language. Autoprefixer swoops in at build time to analyze your CSS and insert vendor prefixes where needed. It was surprisingly freeing to write in standards-compliant, future-proof CSS again. We were coding for an idealized world of full browser support, and Autoprefixer was quietly taking care of the real-world hassles for us in the background.

At that time, we didn’t really know much about PostCSS. Autoprefixer was just a nice little tool slapped onto our build process that let us more easily write CSS3 rules, but we were still using SASS for custom mixins, variables and nesting. We soon discovered that Autoprefixer was just one of many postprocessing plugins living within the PostCSS ecosystem.

We’re not going to claim that PostCSS can approximate everything you might already be doing in SASS. That said, considering its relatively short existence, we were impressed by just how mature and full-featured the software and its accompanying ecosystem of add-ons already are.

The PostCSS build process we’ve come up with works great with Grunt, our existing task runner, and includes the following features:

  • Partials and globbing: Being able to work in small, component-specific files is one of SASS’s best features, and not being able to do the same with PostCSS would’ve been an instant deal-breaker. Luckily, postcss-import handles partials with ease. File globbing – the automatic importing of partials based on a directory pattern – is a love/hate topic in the SASS world, but if you’re a fan, v1.2.0 and the newer grunt-sass-globbing works equally well with PostCSS.
  • Nesting: Much like partials, nesting properties in SASS is a must-have (even though it’s recommend to use them sparingly). We were able to replicate this functionality using postcss-nested.
  • Variables: We leverage postcss-custom-properties, which allows us to write CSS variables (officially known as “custom properties”) straight out of the W3C’s working draft. Honestly, this took the most getting used to, as the syntax (going from $variablename in SASS to var(–variablename) in CSS) is pretty clunky. If you just can’t give up that handy SASS dollar-sign syntax, you could always use postcss-simple-vars instead, but we’ve chosen to write our code in what will someday be the recommended, standards-compliant syntax.
  • Color functions: Unfortunately, you’ll lose SASS’s convenient “lighten” and “darken” functions. But through the use of postcss-color, we’re able to keep the same functionality, while also following the W3C’s proposed CSS Color Module spec. Again, the syntax takes some getting used to, but the functionality works great (and the code we’re writing will someday be standards-compliant).
  • Mixins and extends: The postcss-mixins plugin handles the basic functionality of a SASS mixin or extend. It’s arguably not as powerful as SASS’s equivalents, but we found that most of our mixins weren’t terribly complex to begin with (and if they were, we were probably adding more complexity to our codebase than was actually needed). Another benefit of this plugin is that it gives you the option to write your mixins in pure Javascript, which is a more powerful and natural programming language than SASS.
  • Math: Although not nearly as powerful as Ruby SASS’s built-in arithmetic abilities, postcss-calc does help precalculate CSS calc() rules, which takes a little bit of unnecessary processing away from your users’ browsers.
  • Vendor prefixes: As we mentioned before, the wonderful Autoprefixer doesn’t just write our vendor prefixes for us; it does it automatically. It conforms to the browser support settings we define in a single config file – which can be changed and recompiled on the fly – and unlike SASS, it doesn’t require us as developers to write special function calls or even think about which CSS3 properties are supported by which browsers.

Where Do We Go From Here?

As a team, DEG’s UI developers always try to find a balance. We’re constantly pushing to improve our workflows and processes, but we’re also keenly aware of the fact that chasing the latest UI and development shiny objects can be fruitless and exhausting. Rethinking our development process at such a fundamental level isn’t something we’ve taken lightly.

There’s bound to be some turbulence as we learn more about it, but we’re cautiously optimistic of and excited about our reimagined process. In a field where “the next best thing” can change in an instant, getting back to writing “real” code feels more genuine and pragmatic than any process change we’ve made in a long time.

Stay tuned to this blog series, as we explore the many facets of UI development in a postprocessing world. In future articles, we’re going to delve deeper into the process, benefits and pitfalls of writing future-proof JavaScript, and examine the impacts of this new process on an actual client project. Above all, we’re still learning, and would love to hear your ideas and feedback.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comments