Bringing Laravel’s dump() to Nuxt

Categories: Development

Recently, I’ve been diving deep into Nuxt, and the experience has been fantastic. As a “Full-Stack Vue Framework,” it handles a lot of the heavy lifting, but one classic pain point remains: data visibility.

If you come from the Laravel ecosystem, you’re likely spoiled by dump(), dd(), or the powerhouse that is Laravel Ray. These tools provide instant, beautiful clarity into your data structures.

In the JavaScript world, we often fall back on console.log. While it’s a reliable old friend, it has a frustrating habit of truncating deeply nested objects into a useless [Object] string when viewed in the terminal during SSR (Server-Side Rendering).

Introducing useDump

To bridge this gap, I created useDump. It’s a simple composable designed to give you “Laravel-style” visibility without the terminal headaches.

  • On the Server: It utilizes Node’s util.inspect to render colorized, infinitely deep object trees directly in your terminal.
  • On the Client: It gracefully falls back to the standard browser console.

The Implementation

This composable leverages Nuxt’s built-in environment awareness. By using a dynamic import, we ensure that Node-specific modules never bloat your client-side bundle.

export const useDump = async (...args: any[]) => {
  // 1. Safety first: strictly for local development
  if (process.env.NODE_ENV !== "development") return;

  if (import.meta.server) {
    // Dynamically import Node's util module only on the server
    const { inspect } = await import("node:util");

    args.forEach((arg) => {
      console.log(inspect(arg, { 
        colors: true, 
        depth: null, 
        showProxy: true 
      }));
    });
  } else {
    // Standard logging for the browser console
    console.log(...args);
  }
};

Why use this?

1. Terminal Clarity

No more guessing what’s inside a nested API response. By setting depth: null, useDump forces the terminal to print every single leaf of your data tree.

2. Tree-Shaking Friendly

Because we use import.meta.server and a dynamic await import(), the node:util dependency is completely stripped from the code sent to the user’s browser.

3. Production Stealth

The NODE_ENV check acts as a kill-switch. You can leave your debug statements in place during a frantic dev session without worrying about leaking sensitive state or cluttering logs in your production environment.

Usage Example

You can use it exactly like a standard log, anywhere in your Vue components:

<script setup>
const { data: user } = await useAsyncData('user', () => $fetch('/api/user'))

// On the server, this outputs a beautiful, color-coded tree.
// On the client, it appears as a standard interactive object.
useDump('User Debug:', user.value)
</script>

Final Thoughts

useDump is a tiny addition to your utility folder, but it significantly reduces the friction of SSR development. It brings a slice of that world-class Laravel developer experience into the Nuxt ecosystem, helping you catch data mismatches before they ever hit the browser.


Adam Patterson

Adam Patterson

User Interface Designer & Developer with a background in UX. I have spent 5 years as a professionally certified bicycle mechanic and ride year-round.

I am a husband and father of two, I enjoy photography, music, movies, coffee, and good food.

You can find me on Twitter, Instagram, and YouTube!