farmdev

Thoughts on UI Engineering

Safer TypeScript With Generics And Linting

TypeScript makes JavaScript safer and even opens up new architectural possibilities such as better unit tests. I highly recommend it. However, the default configuration encourages unsafe patterns that developers might not be aware of.

Specifically, I wanted to illustrate the dangers of any and show how you can define custom generics instead. I'll also offer some lint rules that will help your team write safer TypeScript.

read article

Spike, Test, Break, Fix

I first heard about test-driven development (TDD) around 2006-ish and I still hear about it often. TDD encourages you to write effective tests because you always see both states: the failing state and the passing state. This is great but it's easy to write the wrong code for a feature as you learn more about it. Duplicating that exploratory effort on tests is a waste of time.

After many years of building software on small to medium sized teams, I prefer a leaner approach that accomplishes the same goal: something I call spike, test, break, fix.

read article

Profiling And Optimizing React Apps

At Mozilla, the Add-ons team hosts a casual show & tell each month. It's a public meeting and we invite community members to share their work.

This time I demo'd some of the work I've been doing to profile and optimize our code manager, a tool that the review team uses to make sure add-ons are safe for Firefox users. It's a code viewer that looks like an IDE: a file list on the left, code in the middle, and a file overview on the right. The UX is similar to reviewing a pull request on GitHub but the main difference is we integrate our automated scanning tools to provide hints about potential problems.

Watch the demo.

The big challenge we ran into is how to display very large code files and diffs without lag...

read article

The Art of UI Skeletons

A skeleton screen is a technique of rendering placeholders for text, numbers, and other parts of a UI that haven't yet loaded. As a user interacts with the UI, they immediately see the illusion of new screen states—the skeleton—and this makes the app feel very fast. The skeleton layout is typically animated in some way to convey that data is still loading.

My team at Mozilla built addons.mozilla.org with skeleton screens for all loading states. This article covers some of the details about the techniques and approaches we took and some gotchas. It focuses more on the concepts rather than the implementation...

read article

Why Server Side Rendering In React Is So Hard

React first emerged as a powerful way to build living, breathing client side web applications. When my team at Mozilla set out to build a React frontend for addons.mozilla.org in 2016 we knew we needed server side rendering (SSR) for SEO and performance but we underestimated how much of a challenge it would be.

This is a deep dive into how SSR is fundamentally different from what React was designed for...

read article

Safer Unit Testing in React with TypeScript

I hear a lot about how static typing makes JavaScript safer but what about its influence on code architecture? As someone who has worked extensively with dynamically typed languages, I was surprised to realize that type safe applications can be written in entirely new ways.

I'd like to illustrate a fast and effective unit testing strategy that is only possible once you have type safety. I'll be talking about React in TypeScript but this may apply to similar realms...

read article

Testing Strategies for React and Redux

I wrote an article for Mozilla Hacks about testing React / Redux apps.

TL;DR

  • Setting up a test for a Redux connected component is simple: just dispatch the actions needed to enter a desired state. There's no need for mock objects or API calls. If you need to assert that the component dispatches an action in response to a UI event, you can spy on store.dispatch().
  • Shallow rendering lets you run fast, encapsulated unit tests. For example, breakage in an <Icon> component (that might be used all across the app) would not break your entire test suite.
  • Testing component interfaces rather than complete end to end coverage improves encapsulation and makes tests more maintainable. For example, if the component under test passes an onSubmit prop to another component, it's better to simulate the integration by calling otherComponent.prop('onSubmit')(). There's no need to fully mount the other component.
  • I recommend using static typing with these testing strategies to ensure all components are integrated correctly.

read article