Static Assets
Serve static files (HTML, CSS, JavaScript, images) alongside your API exports.
Setup
Set the main field in package.json to your static assets directory:
json
{
"name": "my-app",
"exports": "./src",
"main": "./public"
}Create your static files:
my-app/
├── src/
│ └── index.ts # API exports
├── public/
│ ├── index.html # → /
│ ├── style.css # → /style.css
│ ├── app.js # → /app.js
│ └── images/
│ └── logo.png # → /images/logo.png
└── package.jsonHow it works
When a request comes in:
- API routes are checked first -- if the path matches an export (e.g.,
/greet), the RPC handler responds - Static assets are served -- if no API route matches, the file is served from your assets directory
- 404 is returned -- if neither matches
This means your API exports always take precedence over static files with the same name.
Example: Full-stack app
json
{
"name": "my-fullstack-app",
"exports": "./src",
"main": "./public"
}typescript
// src/index.ts
export async function createUser(name: string, email: string) {
// ... database logic
return { id: 1, name, email };
}
export async function getUsers() {
// ... database logic
return [{ id: 1, name: "Alice", email: "alice@example.com" }];
}html
<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<div id="app"></div>
<script type="module">
import { getUsers, createUser } from "/";
const users = await getUsers();
console.log(users);
</script>
</body>
</html>Powered by Cloudflare Static Assets
Under the hood, this uses Cloudflare Workers Static Assets:
- Global caching -- files are cached at edge locations worldwide
- Automatic compression -- gzip/brotli compression is applied
- Immutable caching -- hashed filenames get long cache lifetimes
Without static assets
If you don't need static files, simply omit the main field:
json
{
"name": "my-api",
"exports": "./src"
}Your Worker will only serve API exports and return 404 for unmatched paths.