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:
// 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:
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:
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:
// 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:
// 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:
- Open React DevTools in your browser
- Each island appears as its own root node in the component tree
- Look for the island file name (e.g.,
Counter.island.tsx) to identify components - 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/$idCheck 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:
bun --inspect devThis starts a debugging server. Connect to it from:
- VS Code --- Add a launch configuration:
{
"type": "bun",
"request": "attach",
"name": "Attach to Bun",
"url": "ws://localhost:6499/",
}- Chrome DevTools --- Open
chrome://inspectand 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:
// 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:
- Check the terminal --- Server errors, loader logs, and build warnings appear here
- Check the browser console --- Client-side errors and island hydration issues
- Check the Network tab --- Verify loader responses and action submissions
- Enable the dev inspector ---
Ctrl+Shift+Dto see route boundaries and timings - Verify file names --- Route files must follow naming conventions
- Clear caches --- Run
rm -rf .ereoto clear the build cache during development - Restart the dev server --- Some config changes require a restart