January 21, 2019

Tailwind Dependency Updates, Pairing Schedule, and 20% Time

Made a lot of progress last week on some interesting projects, and figured out a plan for dealing with some of the stresses I face working by myself, for myself. Good week!

Updating Tailwind's PostCSS dependencies

In my last update, I wrote about a major performance issue I ran into when trying to refactor all of Tailwind's built-in utility modules to plugins. That issue was fixed in PostCSS 7.0.9, but Tailwind was still on PostCSS 6.x, so it seemed like a good time to bump our dependencies and work out any of the kinks.

This was mostly a smooth experience, except (because of course) for one major issue that took a full day to solve.

The issue was that the latest version of postcss-selector-parser included a pretty significant rewrite of how it handles escaping non-standard characters in CSS identifiers (like the : character in classes like sm:bg-blue).

In the version we were using before, the library didn't really handle escaping at all — it just let the consumer worry about it. In the new version, it handles escaping for you, and does it very well. I was excited about this because our hand-rolled escape handling in Tailwind has always felt sort of brittle. It works well enough in practical real-world scenarios, but I bet if someone really went out of their way they could figure out ways to break it.

I started by basically removing all of the escape handling from Tailwind, hoping that I could just rely on this library to handle it all automatically, and it did! But there was one problem — the library it uses under the hood to actually do the escaping (cssesc) handles colons (:) differently than other characters in order to support really old versions of IE.

Instead of simply escaping them as \:, it escapes them as \3A, so selectors like sm:bg-blue are represented in CSS as .sm\3A bg-blue. This is fine and even correct (browsers will handle this properly no problem) but it lead to another issue because of a bug in webpack's css-loader plugin — for whatever reason it strips the leading slash from selectors like this and breaks the CSS entirely.

This is a big problem for Tailwind because : is our default separator character for all of our variants. I opened an issue on the cssesc repo asking if they would consider dropping IE 7 support as that would "fix" the problem even though the real issue is in css-loader, but I had to come up with a solution I could control just in case they turned it down.

I considered forking both postcss-selector-parser and cssesc to make the change myself, and then relying on the forks inside of Tailwind, but that sounded like a bad idea long term.

Eventually I discovered that postcss-selector-parser has an API for manipulating class names while bypassing the escape handling, effectively letting us handle the escaping ourselves like we had been doing previously. I pulled my old escaping code back in, updated everything to use that API, and things were back to working as they should.

Long term I would still like to offload this escape handling to postcss-selector-parser instead of managing it ourselves, but for now this seems like the best solution.

You can check out the pull request that includes these changes on GitHub.

Pair Programming Schedule

After rewriting all of Tailwind's internal utility modules as plugins, the next big project I wanted to tackle for Tailwind 1.0 was restructuring the default config file (I'll write about this in a lot more detail in the next update — it's something I'm working on this week.)

The challenge for me with this project is that it involves a ton of decisions and trade-offs, and making those decisions by myself is completely paralyzing.

I really love pair programming, and I've always felt incredibly productive when I have someone else to lean on when tackling hard design problems. But because I work for myself, it can be really hard to find opportunities to collaborate.

I talked to Jonathan Reinink about this because we've done a lot of pairing in the past, and we decided to throw some recurring events on the calendar where every Tuesday he pairs with me on one of my projects for two hours, and every Wednesday I pair with him on one of his projects for two hours.

This was our first week doing it and it went really well — it was so much easier to come up with solutions when I had someone else to gut-check my ideas.

I had a great time working with him on his project too, and I think it will be a good way to get exposed to problems that I might not run into in my own work very often.

I was also able to pair with my friend Sam Selikoff for a couple hours this week on the same Tailwind config restructuring stuff, and that was super productive as well.

Really looking forward to seeing how this schedule plays out long term.

20% Time

One of the biggest things I stress about and by far my biggest source of impostor syndrome is that I don't really have any real apps I work on.

I make a living creating and selling books and courses, and now I am spending most of my time on Tailwind CSS. This is awesome, but at the same time it means that over the last year, I've basically had no reason to write a line of Laravel code, and the only Vue stuff I've done has been examples for my Advanced Vue Component Design course or little demos for conference talks.

I really want to find a good reason to get deep into writing some real code and building real software, but that's just not my job anymore. And the really scary part is that I need to build software products to be good at my real job, which is making it easier for other people to build software through teaching and tooling.

Making Tailwind the best it can be is hard if I'm not dog-fooding it on something real.

I don't feel like I have this totally figured out yet, but what I've decided to do for now is give myself permission to build a few things on the side, even if they aren't directly contributing to my actual business.

My plan is to spend one day a week working on an app instead of Tailwind or course/book related stuff. I wish I had an idea for something I could actually release and have other people use, because I think that would be the best way to keep leveling up my experience and to keep finding new and interesting ideas to contribute back to the Laravel and Vue communities, but I don't, so some sort of not-so-serious project is going to have to do for now.

Right now I'm leaning towards building a simple bookkeeping tool for my own business, because I hate everything out there that I've tried.

I'm hoping to use it as a playground for eventually developing a few different skills:

  • Building my first proper SPA. Up until now, everything I've ever built has been more traditional server-rendered stuff. I'd like to build a real fat-client JS app at least once, because I think the community is still lacking a lot of info around best practices and patterns, and I'd like to learn how to do this stuff properly so I can share what I learn.
  • Learning GraphQL. I probably won't start the project using GraphQL because I don't want to get overwhelmed learning too many things at once, but eventually I'd like to incorporate GraphQL into this project.
  • Crafting rich, complex user interactions. I really want to use this project as an opportunity to get a lot better at things like animation, and just generally pouring a ton of effort into making the UI as polished as possible.

I've been wanting to get back into live-streaming on a regular basis as well, so I'm hoping this will serve as a source of good content for my audience too.

I'll probably use this time to explore and learn other technologies as well, even if they aren't directly related to the bookkeeping tool I'd like to build.

Last week for example I spent a day learning the basics of Firebase, with the hopes that I could use it to build a very simple comment system for my work journal. I made pretty good progress on it, so with any luck I'll get that wrapped up and added to the site over the next couple of weeks.

Other stuff

A few other things worth noting from last week:

  • Released a new Full Stack Radio episode. I had an awesome conversation with Sam Selikoff about SPA architecture. The full interview was over an hour and a half long so I decided to split it into two parts — the first one (out now) that talks mostly about best practices for storing and retrieving data, and part two (out next week) which focuses on how to keep your complexity contained within the client-side app and out of your API.
  • Paired with Taylor on the next secret Laravel project. We spent three hours on Friday afternoon pushing his next project past a pretty major milestone and had a ton of fun doing it. Looking forward to continuing to be more deliberate about finding opportunities to pair with my friends on their projects.
  • Worked out with Steve. I used to be a pretty competitive powerlifter, but after some annoying injuries sort of got out of the habit a few years ago and have barely lifted over the last few years. Steve wanted to get into working out so now he comes by once a week to train which has been great so far. We've only done two workouts but I'm optimistic that training together is going to keep us both accountable and consistent.

This week

My main focus this week is finishing this big Tailwind config file restructuring. It's a pretty big project because it affects some things internally, but I got a lot of the hard work done last week and am pretty close to being able to open an initial PR. After that I'd like to do some work on making the upgrade path really easy, and add some features to the CLI to give you some options for how you want to generate the new config file.

Again, will talk about all this stuff in tons of detail in the next journal update.

With any luck I'll get a v0.8.0 release out this week that includes these changes as sort of a 1.0 preview.