Latest Post

Write Functional Tests & Assertions

Today while addressing a bug in Amplify JS, I found a passing test that was broken:

expect(reject).toBeCalled();

It turns out, the implementation had a runtime error in it:

try {
someUndefinedFunction();
} catch (error) {
// ReferenceError: someUndefinedFunction is not defined
reject(error);
}

But because the expect only tested that an error happened, we couldn't differentiate between an expected vs. unexpected error.

Open-Source Projects

Illustration of projects

  • mdx-site - Static site generator powered by TypeScript, MDX, & React.

  • polydev – Faster, route-centric development for Node.js apps with built-in Hot Module Replacement.

  • benefit – ✨5kB utility CSS library that is compatible with TailwindCSS.

  • node-recorder – Simple recording & replaying of HTTP requests for predictable development & testing.

  • per-env – Clean up your package.json with per-NODE_ENV npm scripts.

  • react-resolver – Async rendering & data-fetching for universal React applications.

  • npm-install-webpack-plugin – Speed up development by automatically installing & saving dependencies with Webpack.

  • start-server-webpack-plugin – Automatically start your server once Webpack's build completes.

Blog

Illustration of a page

Write Functional Tests & Assertions

Today while addressing a bug in Amplify JS, I found a passing test that was broken:

expect(reject).toBeCalled();

It turns out, the implementation had a runtime error in it:

try {
someUndefinedFunction();
} catch (error) {
// ReferenceError: someUndefinedFunction is not defined
reject(error);
}

But because the expect only tested that an error happened, we couldn't differentiate between an expected vs. unexpected error.

Filesystem Routers & Indexes

Soon, Next.js will support FS-based routes, like Sapper, Nuxt.js, and my own polydev and mdx-site.

But, there's one design decision I've made that differs from the rest: all routes are index-based.

GraphQL Context & Services

sandbox

Having used GraphQL for quite some time, two of my favorite patterns are:

  • Context as a class

  • Abstracting complexity into Service APIs via context.services

Work on Features, Not Repositories

Starbucks’ iOS App

Why organizational boundaries shouldn’t change where development happens.

Jest Snapshots for Storybook

Storybook “stories” convert React components into a testable playground.

Storybook is an extremely powerful & productive way to build React components. They’re effectively tests, so it makes sense to version them along with the rest of your test-suite.

I Ditched My iPhone for the Google Pixel.

Note: Several people were genuinely surprised and were curious what my reasons were, as I was an OG iPhone user.

tldr; Google ecosystem > Apple ecosystem, & the UX is better.

Teaching React Without Using React.

Over a month ago, our remote team of front-end developers visited our Houston office for meetings, social outings, and knowledge sharing.

This team typically works on WordPress sites using PHP, HTML, SASS/LESS/CSS, I wanted to introduce them to React, as it’s been the foundation of our major applications for 2 years.

Hydra, a precursor to GraphQL

Hydra (v1), 2013

This post was sparked by Lee Byron’s excellent writeup on how several Facebook projects (such as GraphQL) came about:

Why Invest in Tools?

Dogfooding Your Open-Source Projects

There’s a discernible, stark difference libraries created as an idea compared to those out of a business need.

The evolution tends to look like:

  1. Initial release of the experiment.

  2. Discovery through external “What about…”, “What if…” and “How do I…” issues.

  3. </Refactor>

  4. Author(s) personally use it in real-world scenario.

  5. </Refactor>

  6. Nailed it.

Javascript Fatigue

A few days ago, I met up with a friend & peer over coffee.

Saul: “How’s it going?” Me: “Fatigued.” Saul: “Family?” Me: “No, Javascript.”

More accurately, I meant React and the Javascript ecosystem that comes with it.

3 Ways to Define Webpack Loaders

Webpack loaders are executed opposite of how many expect (right-to-left when a string, bottom-to-top when an array) such that the final loader returns Javascript.

Once you get past that, the next implementation detail to contend with is writing query parameters to configure each loader, which can get unwieldy.

“Give Back Friday” or “Refactor Friday”

It’s been an incredible year for my team & technology.

We’ve managed to build isomorphic React apps with async data-fetching & rendering thanks to react-resolver, leveraged Redux (which is where the community is this week) for managing state, css-modules to encapsulate our components’ CSS, webpack for building it all for both the server & client, and finally deploying using Docker via CoreOS.

React & event.preventDefault()

We recently shipped a UX improvement where we replaced our simplistic address fields with a Google Place Autocomplete Address Form.

Queue broadcast voice…

Writing Paralysis

Since the start of 2015, I’ve learned more & solved more problems than I have in the past 3 years.

Sure, I have the benefit of forgetting all of the cruft over the past three years, but the coded products are a testament to years of maintaining the status quo compared to months of growth.

Why I Don’t Support Windows

I saw that Github Desktop is entering a private beta and, like a glutton for punishment (or a harsher Biblical expression), I had to see what those on Hacker News had to say about it:

No Linux support? Really? — thecrub

Résumé Tips for Programmers

Short on time? Just hit up the headings!

— Love, Eric

Circular Dependencies in Node

It's inevitable: you will have circular dependencies at some point in your project.

Unfortunately, I've had this issue time & time again and didn't quite realize why it was happening until recently.

Angular Trust Filter

It seems every Angular project I write, at some point, sees the error:

Attempting to use an unsafe value in a safe context.

This is because of Angular's [$sce][1] service, which enabled by default:

SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for security vulnerabilities such as XSS, clickjacking, etc. a lot easier.

Unfortunately, it can be cumbersome, especially when working with dynamic objects.

Simple Node Cluster

After much testing of our internal API, we made it available for several sites to use & got terrible performance.

Of course, we got better performance with Node than we did with PHP, thanks to async parallelizing functions, but we didn't think too much about Node's single-threaded nature.

We already had several sites using the API with more being added daily, all causing performance to quickly dwindle.

Copying Databases in Node

Yes, there are tons of great, StackOverflow-accepted ways to copy giant databases betweens servers. But, sometimes you have a special need for a project that requires selectively copying subsets of data instead of an entire 15GB database.

So, when you have to programmatically copy rows between databases in Node...

Using HTML5, Not Hash Routes

By default AngularJS' [$locationProvider][1] defaults to URLs like:

http://localhost:3000/#/admin/

If in the future you may decide on one of the following:

  • Your application's URLs will [should have longevity][2].
  • You may switch from AngularJS to [another framework][3].
  • You may render URLs on the server to [improve performance, like Twitter.com did][4].

Then, you should switch to HTML5 routing instead of using the default hash URLs.

Besides, it's easy and takes 2 minutes.

Why I'm Terrible at Finishing

I have [several side-projects][1] that are important to me, all in various stages of completion – some open-source and some private until they reach the ever-moving goal post known as “private beta”. Projects for others I have no problem meeting that goal, but my own projects are in a perpetual state of “polish”.

Track Commits, Not Time

Several times in my career has the issue of tracking developers’ time come up.

Sometimes the result has been disastrous, causing a decline in morale and overall performance. Sometimes the result has been beneficial, as it was already a part of an existing workflow. However, as of now, time tracking has gone from a burden to a byproduct of our workflow.