To bundle or not to bundle?

Issue #231.October 16, 2023.2 Minute read.

Today’s issue: Solid.js takes us to Asgard, Addy Osmani makes us feel a tad guilty for not learning Wasm, and Next.js drops some black magic on Friday the 13th.

Welcome to #231.

Eyeballs logo

The Main Thing

A family wearing scary knit beanies and balaclavas

My family always knew how to bundle

To bundle or not to bundle?

Last week, DHH took a break from racing F1 cars to indulge in his other favorite hobby — making JavaScript developers angry.

His latest target? Bundling.

“The state of the art is no longer in finding more sophisticated ways to build JavaScript or CSS,” he said on stage at Rails World Conf, “It’s not to build at all… and to avoid bundling.”

Here’s why, according to the captain of #TeamNoBundle:

  • Historically, bundling has helped improve performance with waterfalls, code splitting, etc. — but it often adds complexity and increased build time.

  • Thanks to modern browser innovations like import maps and HTTP2, we can just ship our JavaScript files as is, without worrying about using Webpack, esbuild, or Bun.

  • This only works if you’re not using very much JavaScript, but don’t worry, because frameworks like DHH’s Hotwire conveniently let you ship more HTML and less JS by default.

That all sounds great… on a conference stage. But as many developers have since pointed out, it’s not quite that simple:

  • Even with HTTP2 and import maps there can still be significant performance implications, with concurrency limits, increased per-request overhead, and more.

  • Compilers (i.e. TypeScript) still provide lots of benefits to large JS applications, like type safety, code splitting, and other perf optimizations.

  • Not everyone is trying to write as little JavaScript as possible. And for larger JS projects, ditching your bundler could provide little upside for a lot of potential downsides.

Bottom Line: Rule #1 of public speaking is to know your audience. So it’s helpful to keep in mind that this was at a Rails conference, where most people listening probably want to write as little JavaScript as possible, because they want to write more Ruby code.

In that context, #TeamNoBundle might work great. And if you disagree, just know that DHH is the 🐐 of outrage-driven marketing, so your anger only makes him stronger.


Convex logo

Our Friends
(With Benefits)

People bowing down to a cat with the Convex logo

My team after I get them to try Convex instead of Firebase.

Convex helps you build a powerful backend with TypeScript

It’s kind of like someone created Firebase in 2023, but gave it more powerful features and made it easier to use (especially for React apps).

With Convex, you get a full cloud backend that can replace your database, server functions, and glue code. And it’s all 100% type-safe.

What it comes with:

  • A realtime relational DB that’s reactive by default and simple to work with.

  • Easy-to-use server functions that manage dev and prod for you.

  • First-class React support with their React and Next.js client libraries (see the docs).

  • Helpful built-in features like file storage, search, and auth.

It’s perfect for using familiar frontend tools to spin up a fullstack app with a production-ready backend.

Check out the free tier — and see why every dev on Twitter won’t shut up about it.

Pop Quiz logo

Pop Quiz

Sponsored by Snyk

Join Fetch the Flag CTF, hosted by Snyk and John Hammond on October 27-28 to solve 30 hacking challenges and compete for a chance to win a Nintendo Switch. Register now!

What gets logged?

const array = new Array(3).fill([])

s/o to Jonny for this one.

Cool Bits logo

Cool Bits

  1. Remix is officially exploring the use of Vite as an alternative compiler to esbuild. It’s still technically unstable for now, but so was I before my life coach introduced me to psilocybin.

  2. CarbonQA’s high-quality QA services for dev teams gives you a team of dedicated, US-based QA testers. They’ll catch all your bugs and make sure that you never get stuck QA testing your own apps again. 🙏 [sponsored]

  3. Shu Ding from the Next.js team wrote about How we optimized package imports in Next.js, and released the article on Friday the 13th. So it’s obviously full of black magic.

  4. Solid.js v1.8 just dropped with new hydration improvements, de-duping of streaming serialization, and new symbolism from Norse mythology about a burning rainbow bridge that connects Earth to Asgard (not making that up).

  5. Postgres.js claims to be the fastest full featured PostgreSQL client for Node.js, Deno, Bun and CloudFlare.

  6. Martin Sosic wrote an article called On the Importance of Naming in Programming, where he argues that “90% of writing clean code is just naming things correctly.”

  7. Chris Fallin wrote an in-depth article called Fast(er) JavaScript on WebAssembly: Portable Baseline Interpreter and Future Plans.

  8. QX82 is a small Javascript engine that lets you create games and experiences inspired by the look and feel of a retro 80s computer. It won’t make you 14 years old again, but it’ll help you pretend.

  9. Thomas Steiner wrote an article on the Chrome blog about API Improvements for working with files in the browser, thanks to a new dev trial for multiple readers and writers for FileSystemSyncAccessHandle.

  10. Addy Osmani wrote about how Photoshop is now on the web, thanks to the magic of Wasm, WebComponents, Lit, Service Workers, and a few other technologies I’m sure you’ll finally get around to learning here soon.

Pop Quiz logo

Pop Quiz: Answer

What gets logged?

const array = new Array(3).fill([])
console.log(array) // [ ["bytes"], ["bytes"], ["bytes"] ]

The key to understanding this one is in knowing that arrays in JavaScript are reference values.

When you call .fill([]), what you’re really doing is “filling up” the array with three references to the same array. You can kind of think of it like this.

const reference = []
const array = new Array(3).fill(reference)

Where now, array has three elements and they’re all referencing the same reference array. Therefore, if you add an item to any of the three elements, since they all point to the same array, it’s as if you’re adding an item to all of them.

To get the same functionality without the referential weirdness, you can use Array.from.

const array = Array.from({ length: 3 }, () => []);
array[0].push("bytes");  // [ ["bytes"], [], [] ]