Help shape what we build next. Take the AdonisJS developer survey.

Blog

Vite 8 and server-side modules in AdonisJS

Harminder Virk
Harminder Virk
Aug 10, 2026 News

Today, we are releasing version 6 of @adonisjs/vite with support for Vite 8.

Vite 8 replaces the old esbuild and Rollup combination with Rolldown, a single Rust-based bundler used throughout the development and production pipelines. The Vite team reports significantly faster production builds while preserving compatibility with the existing Vite plugin ecosystem.

For most AdonisJS applications, the upgrade is small. Alongside Vite 8 support, this release introduces a workflow for loading Vite-powered modules inside the AdonisJS process.

Upgrading to @adonisjs/vite version 6

Upgrade using AI

Upgrade the dependencies

Install version 6 of the AdonisJS integration and Vite 8.

npm install @adonisjs/vite@6
npm install --save-dev vite@8

React applications should also upgrade the React plugin.

npm install --save-dev @vitejs/plugin-react@6

Vue applications should upgrade the Vue plugin instead.

npm install --save-dev @vitejs/plugin-vue@6

Rename entrypoints

The entrypoints option has been renamed to entryPoints.

adonisjs({
  entrypoints: ['resources/js/app.ts'], 
  entryPoints: ['resources/js/app.ts'], 
  reload: ['resources/views/**/*.edge'],
})

Move static asset globs to the Vite config

Older AdonisJS applications may use import.meta.glob inside their JavaScript entrypoint to include images and fonts that are not otherwise part of the frontend import graph. Vite 8 no longer emits non-JavaScript files through this pattern.

Remove those glob imports from the entrypoint.

import.meta.glob(['../images/**', '../fonts/**']) 

Then register the same files using the assets option.

adonisjs({
  entryPoints: ['resources/js/app.ts'],
  assets: ['resources/images/**', 'resources/fonts/**'], 
})

The files are now processed by Vite, added to the manifest, and available through the asset helper.

Verify the production build

Run the type checker and create a production build. The production build is important because it verifies the entrypoints, static assets, and manifest together.

npm run typecheck
npm run build

Vite 8 and Rolldown

The largest change in Vite 8 is the move to Rolldown . Previous Vite releases used esbuild during development and Rollup for production builds. That arrangement was fast, but it meant maintaining two transformation pipelines with slightly different behavior.

Vite 8 uses Rolldown across the toolchain and Oxc for JavaScript transforms and minification. According to the Vite 8 announcement , Rolldown can produce builds 10 to 30 times faster than Rollup in its benchmarks, while keeping the Vite and Rollup plugin APIs familiar.

The exact improvement will depend on the size and shape of your application. The more immediate benefit is having the development and production pipelines share the same foundation.

Static files outside the import graph

Vite normally discovers files by following imports from an entrypoint. Images, fonts, icons, and documents that are not imported by the frontend code fall outside this graph and will be missing from the production build.

Version 6 adds an assets option for those files.

adonisjs({
  entryPoints: ['resources/js/app.ts'],
  assets: ['resources/images/**', 'resources/fonts/**'], 
})

Glob patterns are processed by Vite and receive content-hashed filenames. When a file must be emitted without changing its contents, use the object form and list its exact path under assets.

adonisjs({
  entryPoints: ['resources/js/app.ts'],
  assets: {
    chunks: ['resources/images/**'],
    assets: ['resources/documents/terms.pdf'],
  },
})

Both kinds of files are registered in the manifest and can be resolved using the asset helper.

Loading Vite-powered modules on the server

Some server-side modules use syntax or transforms that Node.js cannot execute on its own. React Email templates containing JSX and Inertia SSR modules processed by frontend plugins are two examples.

In order to run these modules within the same AdonisJS process you will have to process them through Vite via the serverEntryPoints.

import { defineConfig } from 'vite'
import adonisjs from '@adonisjs/vite/client'

export default defineConfig({
  plugins: [
    adonisjs({
      entryPoints: ['resources/js/app.ts'],
      serverEntryPoints: ['resources/emails/verify_email.tsx'], 
    }),
  ],
})

Then, use the vite.loadServerModule method to load the registered entrypoint from your AdonisJS code.

import vite from '@adonisjs/vite/services/main'

export default class NewAccountController {
  async store() {
    const { default: renderVerifyEmail } = await vite.loadServerModule<
      typeof import('../../resources/emails/verify_email.tsx')
    >('resources/emails/verify_email.tsx')

    const html = await renderVerifyEmail({
      verificationUrl: 'https://example.com/verify/token',
    })

    // Send the email
  }
}

The application code uses the same source path in both environments. During development, Vite transforms and loads the source module. During a production build, Vite bundles the server entrypoint, and the same method loads its compiled output.

This API also replaces the package-specific SSR builds we had before. For example, @adonisjs/inertia version 5 registers its SSR module as a server entrypoint and loads it through the same Vite service.

Give it a try

Version 6 of @adonisjs/vite is available alongside Vite 8. You can read the complete @adonisjs/vite release history , the Vite 8 announcement , the Vite changelog , and the Vite 8 migration guide before upgrading an application with extensive custom Vite configuration.

Share this post