Nordic.js 2017 Recap

Last month I travelled up north to my first JavaScript conference: Nordic.js. The entire conference was a great experience: the speakers, the location, the food, ... Here's a quick recap of my favorite talks.

Read more

Diving Into requestAnimationFrame With Benjamin De Cock

I love this post! requestAnimationFrame is a primitive browser API that doesn’t sound too interesting at first, but once you've grasped some basic concepts, it becomes an extremely powerful tool for dealing with animations in JavaScript.

At its core, requestAnimationFrame doesn’t do much: it’s basically just a method that executes a callback. In fact, there are very few differences between doing requestAnimationFrame(doSomething) and doSomething(). So, what’s so special about it? I’m glad you asked! In short:

  • requestAnimationFrame schedules the callback call on the next repaint
  • requestAnimationFrame passes the callback the current time

There are a few other distinctions, but these are the main benefits. Now, requestAnimationFrame doesn’t create an animation on its own, it’s the sequence of successive callbacks that will make things move on the screen.

My favorite part: since a large part of animating with requestAnimationFrame consists of composing small mathematical expressions, you can apply all sorts of functional programming tricks to your code.

Learn all about it on Benjamin De Cock’s blog

Theme-Based Views in Laravel Using Vendor Namespaces

I'm building a multi-tenant Laravel application. One of the requirements of the project is that every client can have their own theme based on their corporate guidelines. By default a few css adjustments will suffice, but some clients request a completely different template.

Conditionally loading a different stylesheet per client is pretty trivial, but in order to use a completely different view per theme you quickly end up typing the same thing over and over across various parts of your application.

Read more

Introducing Our Company Guidelines Site

We just open sourced our company guidelines site! We previously kept the contents in a private wiki on GitHub, but I'm glad we finally put the time in giving the contents a real home.

Like our docs site, the content is stored in markdown files, which can directly be edited on GitHub. The site deploys whenever something's pushed to the master branch.

As for why we decided to open source it all...

This site contains a set of guidelines we use to bring our projects to a good end. We decided to document our workflow because consistency is one of the most valuable traits of maintainable software.

The contents of this site exist for ourselves—more importantly, our future selves—and for giving future collegues a reference to our way of doing things and their quirks. The guidelines cover workflow, code style, and other little things we consider worth documenting.

Check out the guidelines site

What's in our .babelrc?

A lot has been going in in JavaScript the past few years. One of my favorite things has been the usage of babel, which allows us to write future JavaScript syntax today. The babel ecosystem has tons of plugins and configuration options, I'd like to elaborate on our usage at Spatie.

To provide some context on what we're using this for: we generally build medium-sized, non-SPA projects with Laravel. We're using Laravel Mix to build our assets, which uses Webpack under the hood.

Read more

Generate Pdfs With Google Chrome on a Forge Provisioned Server

This week I needed to export some charts generated with HTML & JavaScript as a pdf file. I already had implemented the charts on a webpage so I wanted a solution that allowed me to use my existing code for the pdfs.

Headless Chrome to the rescue! Chrome can run as a cli tool, and print a pdf file from a url. Al I had to do was make some layout tweaks to make everything printer-friendly.

Read more

Using Registered Event Listeners as Conditionals in Vue

Today I was writing a form component that needed an optional back button. Since the form component is generic, the back button could point to anything.

I decided to use a component event, so the parent can listen to a back event and do it's own thing. Also: The back button isn't always necessary, so I needed some sort of prop to decide if it should be rendered.

Read more

Is Snapshot Testing Viable in PHP?

Christopher Pitt wrote a pretty comprehensive article on one of our latest packages, which is one of my favorite packages I've written at Spatie to date, phpunit-snapshot-assertions.

Ah-ha moments are beautiful and rare in programming. Every so often, we’re fortunate enough to discover some trick or facet of a system that forever changes how we think of it. For me, that’s what snapshot testing is.

You can check out the package on GitHub!

Read the full article on SitePoint

Fragmentation is Fabulous

In a recent Twitter thread, Sebastian McKenzie (Yarn and Babel author) shared his thoughts on the current state of open source. This tweet stood out for me (and he later ironically dubbed it his "most thoughtleader tweet ever"):

Revel in fragmentation and duplication because without it there's stagnation and it stifles innovation.

When someone shares their latest pet project library, it's often met with responses like "What a waste of time, you can already do this with library X!".

There's no need for justification here. Maybe the author wants something that fully matches their use case instead of the 80% that library X does, maybe they want a different internal architecture. Maybe they have bigger future plans in mind, or most importantly, maybe they just want to experiment, learn, and have fun.

Read the full thread on @sebmck's Twitter

Exposing Multiple Vue Components as a Plugin

Quick Vue tip for package authors! If you publish a package that exposes multiple Vue components, you can write a small plugin to install them all at once.

Read more

TypeScript With Laravel Mix

In a recent Spatie project we decided to give TypeScript a shot for the business critical part of a new application. TypeScript provides static analysis to reduce the chance of introducing bugs, to have self-documenting code, and to improve our tooling (autocompletion!)

We've been happily using Laravel Mix since it's release with Laravel 5.4. Luckily, extending Mix isn't too hard with some webpack knowledge. One of my favorite features of webpack is the ability to import a module in your application without caring about what kind of file it actually is. As long as you've configured an appropriate loader, you could import anything from a plain old JavaScript file to an animated gif. This means that if we want to support TypeScript with Laravel Mix, we don't need to change any configuration, we only need to add the ability to bundle TypeScript files.

Since writing this post, TypeScript has become officially supported in Laravel Mix (version 0.12 and up). There's still some informative stuff in here if you're new to TypeScript, but use the official method if you're on a newer version of Mix!

Read more

The List Function & Practical Uses of Array Destructuring in PHP

PHP 7.1 introduced a new syntax for the list() function. I've never really seen too much list() calls in the wild, but it enables you to write some pretty neat stuff.

This post is a primer of list() and it's PHP 7.1 short notation, and an overview of some use cases I've been applying them to.

Read more

Automatically Running PHPUnit With Watchman

A little bash script to run tests when a file has been changed.

Since writing this post, we've realeased a pretty awesome PHPUnit watcher CLI tool that's easier to set up and has an interactive interface. You might want to use that instead!

Read more

A Package for Snapshot Testing in PHPUnit

The gist of snapshot testing is asserting that a set of data hasn't changed compared to a previous version, which is a snapshot of the data, to prevent regressions. The difference between a classic and an is that you don't write the expectation yourself when snapshot testing.

When a snapshot assertion happens for the first time, it creates a snapshot file with the actual output, and marks the test as incomplete. Every subsequent run will compare the output with the existing snapshot file to check for regressions.

Snapshot testing is most useful larger datasets that can change over time, like serializing an object for an XML export or a JSON API endpoint.

Our package, which exposes a trait to add snapshot testing capabilities to your tests, can be installed via composer and is available on GitHub.

Read more

Non-breaking, SEO Friendly Urls in Laravel

When admins create or update a news item—or any other entity—in our homegrown CMS, a url slug is generated based on it's title. The downside here is that when the title changes, the old url would break. If we wouldn't regenerate the url on updates, edited titles would still have an old slug in the url, which isn't an ideal situation either.

Our solution: add a unique identifier to the url that will never change, while keeping the slug intact. This creates links that are both readable and unbreakable.

Read more

Dealing With Templates in Vue.js 2.0

Vue 2.0 introduced it's own virtual DOM implementation. At first sight, this doesn't seem to have a large effect on the way you write templates. From the docs:

Under the hood, Vue compiles the templates into Virtual DOM render functions. Combined with the reactivity system, Vue is able to intelligently figure out the minimal amount of components to re-render and apply the minimal amount of DOM manipulations when the app state changes.

The virtual DOM makes room for a pretty big piece of optimization: you can now precompile your templates to pure JavaScript, so Vue can skip this step in the browser.

Without precompiling templates in your build pipeline, Vue needs to translate the template string to a JavaScript render function at runtime. This means it takes longer for the initial render to appear on screen for two reasons: your script bundle needs to include Vue's compiler (longer load time), and the template needs to be compiled before it can be used (longer execution time).

This article isn't about Vue's template syntax, but about where and how to define your templates. I wrote this because at the time of writing there aren't really resources that consolidate all the different manners to manage your templates.

Read more

Using a Database for Localization in Laravel

When building a website for a client that wants to be able to manage content, Laravel's language files aren't ideal since you can't edit them without diving into a bundle of text files. We recently decided to drop all the lang files in our custom CMS in favor of persisting translations in the database, which allows us to build a custom interface for managing them.

This post is a quick overview on overwriting Laravel's default translation loader, which means you can keep using the lang method while fetching the translations from a database. Writing a custom loader is easier than it sounds. First we'll set up our translation models, then we'll write our loader, and finally register it in our application.

Read more

Normalize Your Values on Input

Dynamic languages allow us to pass anything as a parameter without requiring a specific type. In turn, this means we often need to handle some extra validation for the data that comes in to our objects.

This is a lightweight post on handling your incoming values effectively by normalizing them as soon as possible. It's a simple guideline worth keeping in mind which will help you keep your code easier to reason about.

Read more

Adventure Time With Webpack

Over the past few weeks I've been migrating our asset pipeline at Spatie from Laravel Elixir (a gulp wrapper) to webpack. Between having endless possibilities, the occasional incomplete section in the docs, and the fact that everyone has slightly different needs for their asset pipeline (which makes examples hard), it has surely been an adventure. I'm going to do a quick summary of my goals, and how I achieved them with webpack. Hopefully there will be some useful snippets in here for when you're setting up your own webpack configuration.

Read more