Skip to content

Debugging

Tools and techniques for diagnosing issues in EreoJS applications.

Dev Inspector

EreoJS includes a built-in dev inspector that overlays route boundaries, loader timings, and island hydration status on your page during development.

Enable it by pressing Ctrl+Shift+D in the browser while the dev server is running, or add it to your config:

ts
// ereo.config.ts
import { defineConfig } from '@ereo/core'

export default defineConfig({
  dev: {
    inspector: true,
  },
})

The inspector shows:

  • Route boundaries --- Highlights which layout and route file rendered each section
  • Loader timings --- Displays how long each loader took to execute
  • Island status --- Shows hydration state (pending, hydrated, errored) for each island
  • Cache hits --- Indicates whether loader data came from cache or was freshly loaded

Console Logging in Loaders

Loaders and actions run on the server. Use console.log in loaders and the output appears in your terminal (where bun dev is running), not in the browser console:

tsx
export const loader = createLoader(async ({ params, request }) => {
  console.log('Loader called with params:', params)
  console.log('Request URL:', request.url)

  const data = await db.posts.findMany()
  console.log('Found posts:', data.length)

  return { posts: data }
})

For structured logging, use context.log which includes request metadata:

tsx
export const loader = createLoader(async ({ params, context }) => {
  context.log.info('Loading post', { id: params.id })
  context.log.warn('Deprecated endpoint hit')
  context.log.error('Database query failed', { error: err.message })

  return { post }
})

Source Maps in Production

Source maps are generated by default during bun run build. To enable them in production for better error stack traces:

ts
// ereo.config.ts
export default defineConfig({
  build: {
    sourcemap: true, // 'inline' | 'external' | true | false
  },
})

When deploying, upload source maps to your error tracking service (Sentry, Bugsnag, etc.) and exclude them from the public directory:

ts
// ereo.config.ts
export default defineConfig({
  build: {
    sourcemap: 'external', // Generates .map files without inlining
  },
})

React DevTools with Islands

React DevTools works with EreoJS islands. Each island is a separate React root, so they appear as individual component trees in DevTools.

Tips for debugging islands:

  1. Open React DevTools in your browser
  2. Each island appears as its own root node in the component tree
  3. Look for the island file name (e.g., Counter.island.tsx) to identify components
  4. Use the "Highlight updates" feature to verify that only the island re-renders when its state changes, not the entire page

If islands are not appearing in DevTools, ensure the dev server is running and that React DevTools is installed as a browser extension.

Network Debugging for Loaders and Actions

Loader and action requests appear in the browser Network tab. Look for:

  • Document requests --- Initial page loads that trigger server-side loaders
  • Fetch requests to ?_data=route --- Client-side navigations that fetch loader data as JSON
  • POST requests --- Action submissions from forms

Filter by _data in the Network tab to see only loader data fetches:

?_data=routes/posts/index
?_data=routes/posts/$id

Check the response payload to verify your loader is returning the expected data structure.

Bun's --inspect Flag

Use Bun's built-in debugger for step-through debugging of server-side code:

bash
bun --inspect dev

This starts a debugging server. Connect to it from:

  • VS Code --- Add a launch configuration:
json
{
  "type": "bun",
  "request": "attach",
  "name": "Attach to Bun",
  "url": "ws://localhost:6499/",
}
  • Chrome DevTools --- Open chrome://inspect and click "Open dedicated DevTools for Node"

You can set breakpoints in loaders, actions, middleware, and any server-side code.

Debugging Middleware

Middleware runs before loaders and actions. To debug middleware execution order:

ts
// routes/dashboard/_middleware.ts
import type { MiddlewareHandler } from '@ereo/core'

export const middleware: MiddlewareHandler = async (request, context, next) => {
  console.log('[middleware] dashboard - before')
  const response = await next()
  console.log('[middleware] dashboard - after, status:', response.status)
  return response
}

Middleware executes from outermost to innermost (root layout middleware first, then nested route middleware).

Common Debugging Checklist

When something is not working as expected:

  1. Check the terminal --- Server errors, loader logs, and build warnings appear here
  2. Check the browser console --- Client-side errors and island hydration issues
  3. Check the Network tab --- Verify loader responses and action submissions
  4. Enable the dev inspector --- Ctrl+Shift+D to see route boundaries and timings
  5. Verify file names --- Route files must follow naming conventions
  6. Clear caches --- Run rm -rf .ereo to clear the build cache during development
  7. Restart the dev server --- Some config changes require a restart

Released under the MIT License.