Skip to content

Execution Contexts

Resux has several places where code can run. Choosing the right context keeps apps predictable and avoids putting server-only work into resumable browser handlers.

Context table

ContextWhere it livesWhen it runsUse it for
Moduleresux.config.ts, module specifier, local module fileBuild timeAdd CSS, head entries, route rules, runtime config
Pluginplugins/*.tsApp render/runtime setupProvide app values and shared setup
Request middlewareserver/middleware/*.tsEvery HTTP request before handlers, public files, and pagesHeaders, auth gates, redirects, request logging
Server handlerserver/api/*.ts, server/routes/*.tsMatched HTTP requestJSON APIs, custom routes, private server work
Route middlewaremiddleware/*.tsPage navigation before renderingPage guards, redirects, aborts
Page/layout/component setup.vue filesSSR render and later browser resume when neededHTML, resumable state, async data, handlers
Resumable handler@click, @submit, named handlersBrowser interactionMutate resumable refs and patch bindings
Mounted hookonMounted() in a Resux componentFirst browser resume of that scopeBrowser-only setup tied to a Resux component
Vue islandislands/vue/*.vueBrowser mountFull Vue runtime widgets

Build time

Modules run while Resux is building or preparing the dev manifest.

ts
export default defineResuxModule({
  setup(_options, resux) {
    resux.addCss('/module.css')
    resux.addRouteRule('/secure/**', {
      headers: { 'x-module': 'enabled' }
    })
  }
})

Use modules for app-wide build extension. Do not use modules for request-specific data because there is no request yet.

Request time

Request middleware runs before public files, API routes, server routes, and page rendering.

ts
export default defineServerMiddleware((event) => {
  setHeader(event, 'x-app', 'resux')
})

Server handlers run only when their route matches.

ts
export default defineEventHandler(() => {
  return { ok: true }
})

Use these files for secrets, database access, private tokens, and response-level behavior.

Route middleware runs for page navigation. It can redirect or abort before the page renders.

ts
export default defineResuxRouteMiddleware((to) => {
  if (to.path.startsWith('/admin')) {
    return navigateTo('/login')
  }
})

Route middleware is about page access. Request middleware is about HTTP request handling.

Render time

Page, layout, and component setup runs during SSR. It should produce serializable state and HTML.

ts
const route = useRoute()
const config = useRuntimeConfig()
const count = useState('count', () => 0)

If setup code can run during SSR, avoid direct window, document, browser storage, and browser-only constructors.

Browser resume time

Event handlers and onMounted() run in the browser after a scope is resumed.

ts
onMounted(() => {
  console.log('resumed')
})

function increment() {
  count.value++
}

Handlers should capture resumable values. Use server APIs for private work and Vue islands for full client widgets.

Boundary rules

  • Secrets belong in server handlers, request middleware, or private runtime config.
  • Serializable UI state belongs in useState().
  • SSR or resumable data belongs in useAsyncData().
  • Internal API calls in SSR-capable code should use $fetch() or apiURL().
  • Browser-only libraries usually belong in Vue islands.
  • Response headers and cache behavior belong in server middleware or route rules.

Stable v1 core docs for Resux, with experimental areas clearly marked.