Choosing a frontend framework

A question I've gotten a few times after my talk or sharing Svelte by Example is which frontend framework I'd choose these days.

Here's the good news: these days you can't really go wrong with any of the major frameworks—at least from a technical perspective. React, Vue, Svelte, Angular… all have incredible teams, contributors & ecosystems backing them. Your frontend framework will not be the limiting factor of your architecture.

Choose a framework based on the non-technical needs of your team. If scaling up your team is important, React might make more sense because of its popularity on the job market. On the other hand, if your team hates the mental model of React, don't feel pressured to use it regardless of its popularity. Choose your framework based on how it aligns with your team's programming values, not performance needs. (Unless you're building a Bloomberg terminal.)

My preference these days: I'm split between React & Svelte. (That is, when I'm working on a project I deem worthy of a JavaScript-heavy interface, for others I still prefer vanilla JS or Alpine.) I like them both because they each have a distinct direction. React is as JavaScript as a JavaScript framework can be, while Svelte stays as close to HTML & the DOM as possible. What they have in common is they've chosen a slice of the stack, and double down on enhancing it. I prefer tools with distinct directions.

De-atomization is the secret to happiness

Nat Eliason writes about how we're making it hard for ourselves to become happy by reducing activities to hyper-focussed but anemic versions of them.

We separate “I’m working” and “I’m playing.” We want to make everything extremely efficient, so we opt for going for a run alone instead of trying to link up with people along the way. We need to “be productive” so we don’t work from a coffee shop with friends.

How to get composer to suggest users to install a dependency as a dev dependency

Last week I was installing a mocking framework with Composer and got the following prompt:

$ composer require mockery/mockery
mockery/mockery is currently present in the require-dev key and you ran the command without the --dev flag, which will move it to the require key.
Do you want to move this requirement? [no]?

How cool! I didn't know you could hint Composer to suggest a dependency to be installed as a testing dependency.

After further inspection, Composer determines this based on the tags used for the package

If you add dev, testing, or static analysis keywords to your package's composer.json, Composer will prompt users to install it as a dev dependency.

{
"name": "spatie/tabular-assertions",
"keywords": ["testing"]
}

Cleverness

From The Tao of Pooh:

Remember when Kanga and Roo came to the Forest? Immediately, Rabbit decided that he didn't like them, because they were Different. Then he began thinking of a way to make them leave. Fortunately for everyone, the plan failed, as Clever Plans do, sooner or later. Cleverness, after all, has its limitations. Its mechanical judgments and clever remarks tend to prove inaccurate with passing time, because it doesn't look very deeply into things to begin with. The thing that makes someone truly different — unique in fact — is something that Cleverness cannot really understand.

Think of this next time you write Clever Code.

Laravel export v1

Earlier this week, we tagged spatie/laravel-export v1. I wrote the bulk of this package 5 years ago. (Wow, I was surprised by this, time really does fly sometimes!) But I never tagged a stable version because I wanted to add more features. Instead, I chose the way of Arrakis and decided it was ready for a v1.

Laravel Export was inspired by Next.js. Next allows you to write your React app and access data on the server, to export it to a static site after. Next does this by crawling your routes. I built exactly this for Laravel using our crawler package. After configuring, you can run an artisan command to export your static site to a folder.

php artisan export

This is a great fit for websites you don't want full blown hosting for but just want to drop on something like Vercel or Netlify. Docs & details in the repository!

Sven Luijten: Using interfaces in third-party packages

A post on enums & interfaces. I didn't realize you could implement an interface on an enum!

This way you get the best of both worlds: the default implementations are neatly grouped in an enum, but others can extend using their own class implementing the interface.

enum ColorOption: string implements Color
{
case Red = 'red';
case Blue = 'blue';
case Green = 'green';
 
public function name(): string
{
return $this->value;
}
}

Introducing tabular assertions

Today I tagged v1 of a new testing package: spatie/tabular-assertions. It's a distillation of a testing method I've been using in client projects the past two years. The package supports both PHPUnit and Pest out of the box.

With tabular assertions, you describe the expected outcome in a markdown-like table format.

expect($order->logs)->toLookLike("
| type | reason | price | paid |
| product | created | 80_00 | 80_00 |
| tax | created | 5_00 | 5_00 |
| tax | created | 10_00 | 10_00 |
| shipping | created | 5_00 | 5_00 |
| product | paid | 0_00 | 0_00 |
| tax | paid | 0_00 | 0_00 |
| tax | paid | 0_00 | 0_00 |
| shipping | paid | 0_00 | 0_00 |
");

Tabular assertions have two major benefits over other testing strategies: expectations are optimized for readability & failed assertions can display multiple errors at once.

Screenshot of a tabular assertion diff in PhpStorm

For an in-depth introduction to tabular testing, I've written two separate guides for Pest & PHPUnit.

Inspiration

I haven't come across this exact method anywhere else, so I had to come up with a name. If there's prior art that matches this with a better name, I'd love to know!

The idea was inspired by Jest, which allows you to use a table as a data provider.

Snapshot testing is also closely related to this. But snapshots aren't always optimized for readability, are stored in a separate file (not alongside the test), and are hard to write by hand (no TDD).

Tabular assertions have been a huge help when comparing large, ordered data sets like financial data or a time series. I hope you find it useful too!

Dan Abramov: The two Reacts

Frontend frameworks often use the mental modal that a component (or entire UI) is the result of running state through a pure function. Dan Abromov shares his thoughts on the current state of React with server components.

UI = f(data)(state)

Here's how I interpret it: in the mental model we're used to, a component is a pure function that returns UI based on its props. In this case, a Greeter is rendered on the client.

function Greeter(props) {
return <p>Hello, {props.name}!</p>;
}

Say we have a server component that know who needs to be greeted before the code hits the client. In that case, the name will come from data available on the server.

function Greeter(data) {
return function () {
return <p>Hello, {data.name}!</p>;
}
}

The outer function is executed on the server, the inner on the client.

The true power lies in mixing and matching the paradigms. Say you want to read a translation string on the server, and greet a name on the client.

function Greeter(data) {
return function (props) {
return <p>{data.translations.hello}, {props.name}!</p>;
}
}

Feedback

Before I launched Svelte by Example, I called for early access testers in this newsletter. I don't ask for feedback often, I had to push myself to do this.

Sometimes I'm scared of receiving feedback that I'll agree with, but would push back the release when I want to get it out. Sometimes I'm scared of receiving feedback that could invalidate the entire idea. Sometimes I know there are problems but hope they'll magically go away if I ignore them, feedback might resurface them. Sometimes I'm overconfident and don't think it's worth getting another opinion.

No good excuse to be found. These are fears, and it's worth getting over them. Because if any of them are rooted in truth, they'll com back and haunt me rather sooner than later.

A few people responded to my request (thank you!), and it quickly became clear the ask was worth it. The first version of Svelte by Example became way better because of it. The examples became more consistent, the design improved, a bunch of typos were edited out. I didn't process all feedback. Sometimes it doesn't match what you have in mind, and that's fine.

I've learned my lesson: time to get over myself and ask for feedback whenever I can.