Hacking Nuxt’s 404 logic for maximum awesome (and easy proxying)!

Audun Mo
Audun Mo
Jan 22, 2019 · 4 min read

No no, not what it renders on 404. What it does on 404

Here at FINN small jobs, we’re huge fans of Vue.js. So, when we started reading about Nuxt.js, we got really excited, and quickly added it to our stack. In order to keep our React and JSP pages alive, however, we had to find a way to make it proxy to those pages when they’re requested. So, we tore Nuxt down, took away its 404 rendering, and injected our own logic to proxy when there’s nothing to render. Here’s how you can too!

Wait, what the heck is Nuxt?!

Nuxt is a framework built on top of Vue that handles both the client-side and server-side of things. It reduces boilerplate, has server-side rendering out of the box, and lots of other great things. It helps you to get started using Vue without having to worry too much about config, and has best practices included.

This post is aimed at people who are using Nuxt actively, but if you’re a dev just scrolling through, that’s about all you need to know.

Why would I want to override Nuxt’s behaviour?

Well, in our case it stemmed from wanting to proxy to our old app when requests come through that our Nuxt app doesn’t have a view for. This achieves a few things

  • We don’t have to move our entire app in one go
  • We don’t have to manually write rules for every view in our legacy app into our proxy
  • We still get all the advantages of Nuxt and server-side rendering

How does Nuxt handle requests?

Before we can talk about how to hack it, we need to understand how Nuxt handles requests and errors. Under the hood, Nuxt acts mostly like a normal Connect style Node.js server; all the logic is built on a set of middleware functions, including the routing of requests.

In Nuxt the way you add a middleware is by creating a middleware function, then wiring it up in your nuxt.config.js file

Note, these middleware are Connect style, not Express style. This means that you don’t have access to all the convenience methods from Express on req and res

So far so good! Now we have a middleware that runs on all requests. Now how do we override the logic for 404?

Those of you who work a lot with Connect/Express apps might guess that you can inject a regular Connect error handling middleware (a regular middleware, just with the signature (err, req, res, next) ) however Nuxt doesn’t treat 404 like an error. That means that your error handler never sees that there’s an issue.

This is where we wander into undocumented territory of Nuxt. Extending what Nuxt renders on 404 is easily achieved. Changing its behaviour is not so.

Breakdown of the problem

  • Nuxt doesn’t give middlewares an easy way to see if a route is valid or not
  • Nuxt runs its own 404 handler that can’t be intercepted in the middleware chain
  • Nuxt doesn’t have a clearly documented way of overriding the 404 handler on the server side

What we need to do

  • Intercept all traffic and check if the requests are renderable by Nuxt
  • Proxy all other requests

How we did it

The first step is to figure out which routes are renderable by Nuxt. Fortunately, Nuxt’s builder hooks and modules are really helpful here. We can write a module that writes all valid routes to file at build time!

Now every time the app is built, our module saves all the route paths as an array to a file called nuxtPageRoutes.json

This means that we can make the routes available to our middleware. One step closer!

Next, we have to take these path-literals and make them into regexes. Luckily for us, we can use the library that Connect and Express uses under the hood, path-to-regexp! Run yarn add path-to-regexp or npm install path-to-regexp to add it to your project.

Now that we have that in place, let’s return to our override404.js middleware and make it hijack the 404 logic!

And there it is! 🎉 We now have a fully functioning proxy that intelligently proxies our traffic, renders our new app with SSR, and lets us migrate in phases with minimal disruption to our other work.

tl;dr: write a Nuxt module that writes all routes to a file on build, read those routes in a serverMiddleware, convert them to regexes with pathToRegexp , check incoming requests against those regexes, if there’s a match pass it further down the middleware chain, if there’s no match run your own function.

Ps, you can follow my ramblings and musing over on twitter if you like, @artlovecode

FINN.no Blog – Product, Design, and Tech

Posts from the people building the world’s greatest…