Skip to main content
Frameworks

Vite on Easel

Deploy Vite applications to Easel as globally cached static sites and single-page applications.

Easel supports React, Vue, Preact, Solid, Svelte, and other client-side applications built with Vite. Frameworks that use Vite for server rendering, such as SvelteKit, Nuxt, React Router, and TanStack Start, should use their dedicated framework guide.

At a glance

Support levelProduction-ready
RenderingStatic and client-side rendered
Server runtimeNone
Adapter requiredNo
Automatic detectionYes
Default output directorydist
Most recently tested withVite 7.x

Deploy a Vite application

Easel detects Vite projects automatically.

Create a project and connect the project’s Git repository, or deploy with the CLI:

easel deploy

Easel detects the package manager, installs dependencies, runs the production build, and deploys the generated files to the Easel CDN.

The default build command is:

vite build

Most projects define this through a package script:

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

The default output directory is:

dist

You can override the install command, build command, root directory, output directory, Node.js version, and environment variables in your project settings.

Why run Vite on Easel?

Vite applications deploy to Easel as immutable static assets distributed through the global CDN.

A Vite deployment includes:

  • Automatic framework and build-command detection
  • Immutable JavaScript, CSS, image, font, and media assets
  • Global CDN delivery
  • Configurable redirects, rewrites, and response headers
  • Single-page application routing
  • Preview deployments for every branch and pull request
  • Built-in traffic analytics, logs, WAF, and attack protection
  • Atomic deployments with instant rollback

Static Vite applications do not invoke Easel Functions during page requests. This keeps request handling fast and avoids function compute charges.

What Easel deploys

Vite transforms your source code into browser-ready static files. Easel uploads those files to its CDN and serves them directly.

Vite outputEasel resource
index.htmlCDN asset
JavaScript bundlesImmutable CDN assets
CSS bundlesImmutable CDN assets
Imported images and fontsImmutable CDN assets
Files from publicCDN assets
Source mapsCDN assets when included
Client-side routesCDN rewrite to index.html

Assets with content hashes in their filenames can be cached for long periods because a changed asset receives a new URL.

HTML files use shorter cache lifetimes so new deployments can become visible without requiring users to clear their browser cache.

Supported features

CapabilitySupportNotes
Static sitesSupportedBuild output is served through the Easel CDN
Single-page applicationsSupported with configurationRequires a fallback rewrite to index.html
ReactSupportedIncludes standard Vite React projects
VueSupportedIncludes standard Vite Vue projects
PreactSupportedIncludes standard Vite Preact projects
SolidSupportedIncludes standard Vite Solid projects
SvelteSupportedFor client-rendered Svelte applications
TypeScriptSupportedCompiled through the Vite build
CSS modulesSupportedProcessed during the build
Static asset importsSupportedEmitted into the build output
Files from publicSupportedCopied to the output root
Custom base pathsSupportedConfigure with Vite’s base option
Client environment variablesSupportedVariables must use the VITE_ prefix
MonoreposSupportedConfigure the project root directory
Custom output directorySupportedConfigure the same directory in Vite and Easel
Redirects and rewritesSupportedDefined in project configuration
Custom response headersSupportedDefined in project configuration
Server-Side RenderingNot provided by plain ViteUse a supported full-stack framework
API routesNot provided by plain ViteDeploy an Easel Function or use a full-stack framework
MiddlewareNot provided by plain ViteUse Easel routing and security configuration
WebSocketsNot provided by static hostingRequires a persistent external service

Single-page applications

Client-side routers use browser history APIs to render multiple routes from one HTML entry point.

For example, a React application may handle all of these routes in the browser:

/account
/account/settings
/projects/123

When a visitor opens /account/settings directly, Easel must serve index.html rather than look for a file at that path.

Add a fallback rewrite in vercel.json at the project root. Easel accepts this portable routing format:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}

Easel applies the rewrite only when handling the request. The browser URL remains unchanged, allowing the client-side router to render the requested route.

Avoid rewriting static assets

A broad SPA fallback should run after Easel checks for a matching static file. Requests for JavaScript, CSS, images, fonts, and other generated assets continue to resolve to their files.

A missing application route receives index.html, while a missing asset should still return a 404 response.

Framework routers

The same fallback model works with common client-side routers, including:

  • React Router in declarative or data mode
  • Vue Router
  • TanStack Router
  • Solid Router
  • Preact Router
  • Svelte SPA routers

React Router framework mode includes a server build and should instead use the React Router framework guide.

Static sites with multiple HTML pages

Not every Vite application is a single-page application.

Vite can produce multiple HTML entry points:

import { resolve } from "node:path";
import { defineConfig } from "vite";

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        home: resolve(__dirname, "index.html"),
        about: resolve(__dirname, "about/index.html"),
        pricing: resolve(__dirname, "pricing/index.html"),
      },
    },
  },
});

Easel deploys each generated HTML file at its corresponding path:

Generated fileURL
dist/index.html/
dist/about/index.html/about/
dist/pricing/index.html/pricing/

Do not add an SPA fallback rewrite when each route has its own generated HTML file.

Environment variables

Vite exposes variables prefixed with VITE_ to application code through import.meta.env.

Configure the variable in the Easel dashboard or CLI. See deployment environments.

VITE_API_ORIGIN=https://api.example.com

Read it in the application:

const apiOrigin = import.meta.env.VITE_API_ORIGIN;

Public variables

Every variable exposed through import.meta.env is included in the browser bundle.

Do not place secrets in variables prefixed with VITE_, including:

  • Database credentials
  • Private API keys
  • Signing keys
  • Service-account credentials
  • Authentication secrets

A visitor can inspect these values in downloaded JavaScript.

Use an Easel Function or another server-side service when an operation requires a secret.

Build-time behavior

Vite replaces client environment variables during the production build. Changing a VITE_ variable requires a new deployment.

Use separate environment values for production, preview, and development when the application connects to different services in each environment.

Built-in variables

Vite also provides built-in environment values:

import.meta.env.MODE;
import.meta.env.BASE_URL;
import.meta.env.PROD;
import.meta.env.DEV;
import.meta.env.SSR;

For a static Easel deployment, import.meta.env.SSR is false in browser application code.

Base paths

Vite assumes the application is served from / unless you configure a different base path.

For an application deployed at:

https://example.com/dashboard/

set base in vite.config.ts:

import { defineConfig } from "vite";

export default defineConfig({
  base: "/dashboard/",
});

Vite prefixes generated JavaScript, CSS, and asset URLs with that path.

The Easel deployment route and Vite base path must agree. A mismatch commonly causes the HTML page to load while JavaScript or CSS requests return 404.

For a root-domain deployment, leave the default base:

import { defineConfig } from "vite";

export default defineConfig({
  base: "/",
});

Asset handling

Imported assets

Vite processes assets imported from source code:

import logoUrl from "./logo.svg";

Small assets may be embedded into JavaScript or CSS. Larger assets are emitted into the output directory with content-hashed filenames.

Easel treats these hashed files as immutable CDN assets.

Public directory

Files placed in Vite’s public directory are copied to the root of the build output without content hashing.

For example:

public/favicon.ico

becomes:

dist/favicon.ico

and is available at:

/favicon.ico

Because public files do not receive content hashes, update their filenames when you need to guarantee immediate cache invalidation.

Source maps

Vite does not emit production source maps by default.

Enable them in vite.config.ts:

import { defineConfig } from "vite";

export default defineConfig({
  build: {
    sourcemap: true,
  },
});

Source maps may contain original application source. Upload them to your error-monitoring provider or restrict their public availability when exposing source code is a concern.

Cache behavior

Vite generates content-hashed filenames such as:

assets/index-Cg4kP8nD.js
assets/index-D7hA2xLm.css

Because the filename changes whenever its contents change, Easel can cache these assets aggressively. See Cache responses at the edge.

A Vite deployment uses different policies for different resources:

ResourceBehavior
Hashed JavaScript and CSSLong-lived immutable caching
Hashed images and fontsLong-lived immutable caching
HTML entry pointsShorter caching with revalidation
Files from publicConfigurable, depending on filename strategy

Easel deployments are atomic. A new deployment publishes a complete new set of assets rather than updating files in place.

Older deployment URLs continue pointing to their original asset set, which prevents a preview or rollback from accidentally loading bundles from another deployment.

Redirects, rewrites, and headers

Vite does not define production routing behavior itself. Configure application-level routing in project configuration.

Common use cases include:

  • Redirecting an old route to a new route
  • Rewriting SPA routes to index.html
  • Adding security headers
  • Defining cache behavior
  • Proxying a path to another service
  • Redirecting between apex and www domains

For example, redirect an old documentation path:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [
    {
      "source": "/docs-old/:path*",
      "destination": "/docs/:path*",
      "status": 308
    }
  ]
}

Add security headers:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        }
      ]
    }
  ]
}

When importing an existing project, Easel can also interpret supported configuration formats from compatible platforms.

APIs and server-side code

Plain Vite applications contain browser code and static assets. Vite does not create an application server or API runtime.

When the application requires server-side behavior, you can:

  • Deploy an Easel Function
  • Connect to an external API
  • Use a supported full-stack framework
  • Use a managed backend or database service

Do not place private credentials directly in the Vite application to call a protected upstream API. Browser users can inspect those credentials and make requests independently of the application.

An Easel Function can keep the credential server-side:

export default async function handler(request: Request) {
  const response = await fetch("https://api.example.com/private-data", {
    headers: {
      Authorization: `Bearer ${process.env.PRIVATE_API_KEY}`,
    },
  });

  return new Response(response.body, {
    status: response.status,
    headers: {
      "Content-Type":
        response.headers.get("Content-Type") ?? "application/json",
    },
  });
}

The Vite application can then call the function using a relative URL:

const response = await fetch("/api/private-data");
const data = await response.json();

Monorepos

Set the Easel project root to the directory containing the Vite application.

For example:

apps/
  dashboard/
    package.json
    vite.config.ts
  api/
    package.json
packages/
  ui/
package.json

The Vite project root would be:

apps/dashboard

Easel runs the install and build commands from the configured project context while preserving access to workspace dependencies.

Ensure the package manager’s lockfile is available from that context. Depending on the workspace layout, the install command may need to run from the repository root even when the build command targets a nested application.

Custom output directories

Vite writes production files to dist by default.

To use another directory:

import { defineConfig } from "vite";

export default defineConfig({
  build: {
    outDir: "build",
  },
});

Set the Easel output directory to the same value:

build

If these settings differ, the build can succeed while Easel reports that it cannot find deployable output.

Avoid writing the build output outside the project workspace unless the Easel build environment explicitly permits that path.

Local development

Continue using Vite’s development server:

npm run dev

Vite’s development server provides hot module replacement and framework-specific development behavior.

Use Easel preview deployments to validate production platform behavior, including:

  • Production minification and bundling
  • SPA fallback rewrites
  • Redirects and custom headers
  • CDN caching
  • Environment-specific variables
  • Base paths
  • WAF and security rules
  • Custom domains

A preview deployment runs the same static deployment process as production and receives its own immutable URL.

Do not use vite preview as a production server. It is intended only for locally previewing the generated build output.

Static export from other frameworks

Some frameworks can emit fully static output through Vite or a related build process.

A static export can be deployed through the Vite path when the final output consists only of HTML, JavaScript, CSS, and other static files.

However, using a static export removes server-dependent framework features such as:

  • Server-Side Rendering
  • Server Actions
  • API routes
  • Middleware
  • Runtime cache revalidation
  • Request-time personalization

Use the framework’s dedicated Easel guide when the application requires any server runtime behavior.

Known limitations

No server runtime

A plain Vite deployment does not include a Node.js or edge server. Server-only modules and Node.js APIs cannot run in browser code.

For example, the following cannot execute in the deployed frontend:

import fs from "node:fs";

Move server-side logic into an Easel Function or a supported full-stack framework.

No hidden environment variables

Variables included in the Vite client bundle are public. The VITE_ prefix controls browser exposure. It is not a secret-storage mechanism.

Client-side routing requires a rewrite

History-based routes return 404 on direct navigation unless an SPA fallback is configured.

Hash-based routing does not require a server rewrite because the URL fragment is not sent in the HTTP request, but history-based routing produces cleaner URLs.

Filesystem paths are case-sensitive

The Easel build environment and CDN treat file paths as case-sensitive.

An import that works on a case-insensitive local filesystem may fail during deployment:

// File is named Button.tsx
import Button from "./button";

Ensure import casing exactly matches the filename.

Troubleshooting

The build succeeds, but Easel cannot find the output

Confirm that the Easel output directory matches Vite’s build.outDir.

The default for both should be:

dist

A client-side route returns 404

Configure an SPA fallback rewrite to index.html.

Do not add this rewrite to a multipage site where each route has its own generated HTML file.

The page loads without JavaScript or styles

Check the browser network panel for asset requests returning 404.

The most common cause is a mismatch between Vite’s base setting and the application’s deployment path.

An environment variable is undefined

Confirm that:

  1. The variable begins with VITE_.
  2. It is configured for the current deployment environment.
  3. The application was rebuilt after the value was added or changed.
  4. The code reads it through import.meta.env.

For example:

const apiOrigin = import.meta.env.VITE_API_ORIGIN;

A variable still has its previous value

Vite embeds client environment variables during the build. Trigger a new deployment after changing the value.

An import works locally but fails during deployment

Check filename casing and verify that the dependency is declared in the appropriate package.json.

Also confirm that the package is not relying on Node.js APIs in browser code.

Refreshing a route returns the home page incorrectly

A broad SPA fallback sends all unmatched routes to index.html. Ensure APIs, static files, and other special paths are handled before the fallback rule.

The application calls the wrong API in preview deployments

Use separate production and preview values for VITE_API_ORIGIN, or call a same-origin relative path when the backend is deployed with the application.

Compatibility policy

Easel tests its Vite integration against representative applications using React, Vue, TypeScript, static assets, client-side routing, custom output directories, base paths, environment variables, and monorepo layouts.

Stable Vite releases may work beyond the version listed at the top of this page, but the listed version is the most recently verified baseline.

Vite plugins that only transform the build output work without platform-specific support. Plugins that expect a persistent server, custom development middleware, or a specific hosting runtime may require an Easel integration or a dedicated framework guide.

Next steps