Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: Enhanced support for static assets with the Cloudflare Vite plugin
description: The Cloudflare Vite plugin now supports using all of Vite's static assets features in your Worker
products:
- workers
date: 2025-07-01T01:00:00Z
---

You can now use any of Vite's [static asset handling](https://vite.dev/guide/assets) features in your Worker as well as in your frontend.
These include importing assets as URLs, importing as strings and importing from the `public` directory as well as inlining assets.

Additionally, assets imported as URLs in your Worker are now automatically moved to the client build output.

Here is an example that fetches an imported asset using the [assets binding](/workers/static-assets/binding/#binding) and modifies the response.

```ts
// Import the asset URL
// This returns the resolved path in development and production
import myImage from "./my-image.png";

export default {
async fetch(request, env) {
// Fetch the asset using the binding
const response = await env.ASSETS.fetch(new URL(myImage, request.url));
// Create a new `Response` object that can be modified
const modifiedResponse = new Response(response.body, response);
// Add an additional header
modifiedResponse.headers.append("my-header", "imported-asset");

// Return the modfied response
return modifiedResponse;
},
};
```

Refer to [Static Assets](/workers/vite-plugin/reference/static-assets/) in the Cloudflare Vite plugin docs for more info.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ description: Static assets and the Vite plugin

import { WranglerConfig } from "~/components";

The Vite plugin does not require that you provide the `assets` field in order to enable assets and instead determines whether assets should be included based on whether the `client` environment has been built.
By default, the `client` environment is built if there is an `index.html` file in the root of your project or if `build.rollupOptions.input` is specified in the Vite config.
This guide focuses on the areas of working with static assets that are unique to the Vite plugin.
For more general documentation, see [Static Assets](/workers/static-assets/).

:::note
When using the Cloudflare Vite plugin, the `client` environment is deployed as your static assets.
This typically includes files such as static HTML, front-end JavaScript, CSS, images and fonts.
For more information about using static assets in Vite, refer to [Static Asset Handling](https://vite.dev/guide/assets).
:::
## Configuration

The Vite plugin does not require that you provide the `assets` field in order to enable assets and instead determines whether assets should be included based on whether the `client` environment has been built. By default, the `client` environment is built if any of the following conditions are met:

- There is an `index.html` file in the root of your project
- `build.rollupOptions.input` or `environments.client.build.rollupOptions.input` is specified in your Vite config
- You have a non-empty [`public` directory](https://vite.dev/guide/assets#the-public-directory)
- Your Worker [imports assets as URLs](https://vite.dev/guide/assets#importing-asset-as-url)

On running `vite build`, an output `wrangler.json` configuration file is generated as part of the build output.
The `assets.directory` field in this file is automatically populated with the path to your `client` build output.
Expand All @@ -32,10 +35,34 @@ assets = { not_found_handling = "single-page-application" }

</WranglerConfig>

## Features

The Vite plugin ensures that all of Vite's [static asset handling](https://vite.dev/guide/assets) features are supported in your Worker as well as in your frontend.
These include importing assets as URLs, importing as strings and importing from the `public` directory as well as inlining assets.

Assets [imported as URLs](https://vite.dev/guide/assets#importing-asset-as-url) can be fetched via the [assets binding](/workers/static-assets/binding/#binding).
As the binding's `fetch` method requires a full URL, we recommend using the request URL as the `base`.
This is demonstrated in the following example:

```ts
import myImage from "./my-image.png";

export default {
fetch(request, env) {
return env.ASSETS.fetch(new URL(myImage, request.url));
},
};
```

Assets imported as URLs in your Worker will automatically be moved to the client build output.
When running `vite build` the paths of any moved assets will be displayed in the console.

:::note
If you are developing a multi-Worker application, assets can only be accessed on the client and in your entry Worker.
:::

## Headers and redirects

Custom [headers](/workers/static-assets/headers/) and [redirects](/workers/static-assets/redirects/) are supported at build, preview and deploy time by adding `_headers` and `_redirects` files to your [`public` directory](https://vite.dev/guide/assets#the-public-directory).
The paths in these files should reflect the structure of your client build output.
For example, generated assets are typically located in an [assets subdirectory](https://vite.dev/config/build-options#build-assetsdir).

<br />
23 changes: 17 additions & 6 deletions src/content/docs/workers/vite-plugin/tutorial.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,8 @@ The `main` field specifies the entry file for your Worker code.
### Add your API Worker

```ts title="worker/index.ts"
interface Env {
ASSETS: Fetcher;
}

export default {
fetch(request, env) {
fetch(request) {
const url = new URL(request.url);

if (url.pathname.startsWith("/api/")) {
Expand All @@ -163,7 +159,7 @@ export default {

return new Response(null, { status: 404 });
},
} satisfies ExportedHandler<Env>;
} satisfies ExportedHandler;
```

The Worker above will be invoked for any non-navigation request that does not match a static asset.
Expand All @@ -172,6 +168,21 @@ It returns a JSON response if the `pathname` starts with `/api/` and otherwise r
:::note
For top-level navigation requests, browsers send a `Sec-Fetch-Mode: navigate` header.
If this is present and the URL does not match a static asset, the `not_found_handling` behavior will be invoked rather than the Worker.
This implicit routing is the default behavior.

If you would instead like to define the routes that invoke your Worker explicitly, you can provide an array of route patterns to [`run_worker_first`](/workers/static-assets/binding/#run_worker_first).
This opts out of interpreting the `Sec-Fetch-Mode` header.

<WranglerConfig>

```toml
name = "cloudflare-vite-tutorial"
compatibility_date = "2025-04-03"
assets = { not_found_handling = "single-page-application", run_worker_first = ["/api/*"] }
main = "./worker/index.ts"
```

</WranglerConfig>
:::

### Call the API from the client
Expand Down