Justin Duke

How I cut my Webpack bundle size in half

In the fall, a young man’s fancy lightly turns to thoughts of front-end performance.

When I initially built out Buttondown, I was focused on two aspects above all else:

  1. It being built quickly.
  2. It working reasonably well.

Notably excluded from that list is performance. Buttondown isn’t a slow app, but it is a heavy one: the bundle size while developing is measured in megabytes, and there’s a non-trivial loading time for first-time users.

Now that the core feature base has stabilized and nothing is particularly in an “on fire” state, I wanted to turn my eye towards maintenance work, and a big piece of that was seeing what I could do to shrink that bundle.

Read more →

Not The Keynote You're Looking For

I hate to be in the position of defending Apple evangelists, but there have been a lot of weird takes about the Apple leaks the past few days. Here’s one:

I think the comparison between Star Wars and Apple products is particularly apt because, well, Star Wars isn’t “commercial art”: it’s a meticulously managed piece of intellectual property. It isn’t a singular artistic vision: its the culmination of hundreds of stakeholders, producers, focus testers, and marketers. So much so that the director of a Star Wars movie just got replaced, like a poorly-performing engineering manager:

Lucasfilm and Colin Trevorrow have mutually chosen to part ways on Star Wars: Episode IX. Colin has been a wonderful collaborator throughout the development process but we have all come to the conclusion that our visions for the project differ. We wish Colin the best and will be sharing more information about the film soon.

The primary goal of a Star Wars movie is to entice audiences to engage more in the Star Wars universe: to create buzz, to purchase merchandise, to consume more Star Wars media. It accomplishes this by putting out an entertaining, easily consumable, but unchallenging product. (And, sure, sometimes it gets a little derivative.)

The primary goal of an Apple keynote is to entice the audience to engage more in the Apple universe: to create buzz, to purchase products, to consume more Apple media. It accomplishes this by putting out interesting (albeit comically self-indulgent) marketing material. (And sure, sometimes it gets a little derivative.)

I think it’s weird and unambiguously bad to complain that tech journalists are doing their jobs: of course they’re going to report on the leaks and of course they should report on the leaks.

I also think it’s weird to pretend that Apple fans are any different than Star Wars fans or Marvel fans or of any wildly successful franchise.

There are a lot of things to criticize about Apple, and even Apple fandom. But the act of just being excited about the new shiny things is, I think, harmless and honestly kind of lovely. There’s something so earnest about the idea of people being so excited to watch the keynote and see how their technology is going to evolve.

(For what it’s worth, I watch the Star Wars movies because I love big ol’ adventures, and I watch the Apple keynotes because I am a tremendous nerd. And I think complaining about spoilers is dumb.)


Turning 25

This week, I turned 25.

I spent my birthday doing the thing I want to spend every birthday doing: I reverse seared a filet, bought a nice scotch, and watched an old movie with Molly.

We were going to watch Bridge on the River Kwoi but didn’t want to start a three-hour movie at eight pm, so we watched The African Queen.

We have become so old. It is fantastic.

I do the thing I do every time I turn a new age, which is expressly deny the very concept of maturation until it seeps into my life anyway.

Like grabbing dinner and drinks with a couple friends who had moved out of town but were back for the week, and suddenly understanding that “grabbing dinner and drinks” has become an act that shifted from “order a pizza and go bar-hopping” to “make sandwiches and drink wine”.

(I mean, I still eat pizza, and we still go to bars. But we eat less pizza, and spend less time in bars, and besides on the week of your birthday you’re forced to wonder how things have changed.)

I am re-reading what I wrote this time last year, and discovering that most of my thoughts are redundant. I feel more mature but no more wiser. I feel like I’m getting more rest but am slightly worried about forgetting what it feels like to be restless.

I am waking up early (I referred to waking up at 7 as sleeping in); I am eating well. I find myself so tired at the day, but it’s an earned fatigue (to steal a friend’s phrase.). I am reading and writing and learning French, conjugated word by conjugated word. I can deadlift more than I could deadlift twelve months ago. I beat Persona 5.

And I’m happy. Really, really happy. If there’s something that I’m unhappy about, it’s that the days are short and the weeks are short and the months are the shortest of all.

We’re going to DC in a few weeks, and then after that Paris, and then after that we need to plan our next trip — Tokyo, maybe, or Edinburgh or Prague. And then after that, maybe Little Rock. I have always wanted to visit Little Rock, for reasons unexplainable.

There is still so much to discover.


Creating a password validator component in Vue

Sometimes you procrastinate one feature by writing another. Even if that other feature is pretty small and inconsequential. 1

For me, that other feature — if you can even call it a feature — was password strength testing for Buttondown.

Read more →

Side Projects: July 2017


  1. Buttondown continues to grow, as does Spoonbill.
  2. Consolidated my web stuff. This site is better than ever, Village Blacksmith is nice and clean.
  3. Still launching dope stuff on Buttondown: I’m particularly proud of its new embed support, which will hopefully integrate with Medium somewhat soon.


  1. Buttondown continues to be unprofitable, as does Spoonbill.
  2. I didn’t launch Very Cute, though I got a bit more progress on it. (I don’t feel that bad about this, because it was a productive month — it’s just that most of my cycles were poured into Buttondown.)

What’s Next

  1. Going to retool Buttondown’s pricing to try and monetize the majority of the user segments who don’t qualify for the current pricing schema. For $19/mo, you can set a custom redirect URL, remove branding, and probably a couple other things.
  2. Sticking to that. I think with the current amount of energy I’m spending on Buttondown it’s prohibitively difficult to work on something else. (More about this later.). There are a couple projects I want to do (React Native version of https://coinmarketcap.com/, public Airtable tracking SaaS prices, simple AWS infoproduct…) but I don’t think I can commit to any of them right now.

Other Thoughts

  • The past couple weeks have been exhausting! My schedule has felt packed to the gills: wake up early, do chores and administrative stuff til 9, then work til 1, then work out, then work until 5 or 6. At that point I’m exhausted and have to choose between working on side projects or doing something fun and active. I’m been choosing the latter as much as possible — which is the right choice — but it means I don’t move the needle as much as I’d like, which means I feel guilty.
  • I’m really tempted to start tracking vanity metrics more, because they’re doing really well. But vanity metrics won’t buy me scotch.

Read more →

Creating a reusable tabbed card component in Vue

I built a thing for Buttondown that lets you embed an iFrame to handle subscriptions really nicely:

Read more →

There are still dragons everywhere

I’ve been programming for the better part of a decade, and I’ve been programming in Python for the better part of that better part.

As loathe as I am to assume the mantel of “X Engineer”, if I were to describe my career in relation to any technology it would be “Python Engineer”.

It is the language I feel most comfortable with; it is the language I reach to first when starting a new project; it is the language I write daily. It is as frictionless as English.

And yet I still find myself losing hours to things I thought I had mastered.

The other night, I played with the idea of bumping Buttondown to Python 3.6 from 3.5 — I wanted cooler types and faster dictionaries, and it seemed like a painless process, so I ran brew upgrade python and was off to the races.

Except something broke: there was an issue with how I was using grequests that was fine in 3.5 but not 3.6, and I decided to revert.

So I hit up pyenv to try and grab 3.5 (since it was no longer the latest thing installed on my machine) and use that to recreate my virtualenv.

Except now psycopg2 was broken for some reason?

It kept on throwing a bizarre error that had like, three matches on Google total:

ImportError: datetime initialization failed

So, I do what I’ve learned to do: nuke everything and start over.

Except now virtualenv is broken, looking for a global python installation that doesn’t exist: no such file or directory, it snaps back at me.

After a few hours of fruitless Googling and tinkering, I do the thing I’m not supposed to do: I just re-install the old version of Python with brew:

brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/ec545d45d4512ace3570782283df4ecda6bb0044/Formula/python3.rb

And suddenly everything works. I recreate the virtualenv; I reinstall the dependencies; I get back to work.

There’s no big lesson here. I probably should have stuck with 3.6 and figured out the grequests issue; I probably should have been more disciplined with installing 3.6 through pyenv and managing my environments.

But I think it feels good to get lost in a sea of arcana and development hell for an afternoon. I mean, it sucks in the moment — there’s no denying that. But once the moment passes, you’re reminded about how much left there is to learn and to master.


App sizes are under control, they just aren't under scrutiny

I wrote at the first of last month about bloat in apps, in response to a thoughtful piece by Ben Sandofsky about how he minimized bloat in Halide.

I had some misgivings with the post and the ideas it espoused — namely, that “bloat is bad” is a reductionist truism — but still admired the approach Sandofsky took and the clear tradeoffs and sacrifices he discussed.

This post by Trevor Elkins making the rounds today has the same message, though it lacks the nuance and pragmatism:

As app developers, we should be more conscious of the space we use. Take some time to remove the cruft that builds up and push back against needless waste.

So really, how does an app that occasionally sends me a connection request and recruiter spam take up 275MB? Maybe I’ll do an analysis at some point, but for now it’s deleted.

Trevor works for Kayak, whose iOS app weighs in at 176 MB.

Perhaps Trevor is actively working on reducing the size of the app bundle, in which case he knows how difficult it is to make decisions like do we spend two weeks reimplementing this framework or just eat the 5MB it adds to our final app size?

Or perhaps he isn’t, but he’s talked with fellow Kayak engineers who have determined that the bloat is worth the cost — maybe they’ve got a lot of high-resolution assets, or have decided that the development velocity a framework-heavy approach enables is worth the drop-off in installs.

Or perhaps he didn’t even know Kayak’s app size is so large in the first place, because it’s a factor that doesn’t impact the majority of users after the initial download. 1

Either way, it’s kinda shitty to insiniuate that an app is bloated due to incompetence; it’s kinda shitty to insiniuate that an app is bloated due to indifference.

Everything is a trade-off. Some companies don’t think it’s worth it to slim down their bundle sizes; some companies do. It’s disingenuous to pretend otherwise.

(For what it’s worth, I think the Kayak iOS app is great.)

  1. Which isn’t to say that it doesn’t impact users — it’s to say that the surface area of the impact is pretty small. [return]

The best podcasts

First, some background and context, because I’m a super persnickety podcast listener:

  1. I think podcasts, like anything else, need to be interesting and timeless. If an episode is useless or pointless to listen to three months after its publication, then its a bad episode; if that describes most episodes, then it’s a bad podcast for me. 1
  2. I don’t like most politics or tech news podcasts, mostly because they end up guilty of the above.
  3. I don’t like comedy podcasts, much to my chagrin. 2
  4. In my experience, most interview-style podcasts are more marketing/PR than actual information. Obviously that’s a broad brush (and a couple of the podcasts on this list are interview podcasts!), but in general I feel like the ROI on interviews are low.
  5. This list is constantly evolving. It was last edited in August of 2017. (And I’m always looking for new things to listen to!)

Read more →

A nice little list of valid and invalid email addresses

Note This is a growing and evolving list! If you see anything that I'm missing, email me and I'll add it.

I’ve been spending a lot of time working on Buttondown lately and, as you might expect for a newsletter app, lots of this work revolves around dealing with email addresses.

In an effort to save myself and others some time, I’m trying to collate a list of usefully distinct and weird invalid and valid addresses for test harnesses and such. Below is what I have so far: it’s not a complete set, but it’s comprehensive enough to handle most of the weirdnesses out there.

Read more →
© 2017 Justin Duke • All rights reserved • I hope you have a nice day.