cache stuff

This commit is contained in:
Corey Johnson 2025-07-11 15:55:02 -07:00
parent 609c793844
commit 98d8b9ef5a
5 changed files with 10 additions and 108 deletions

View File

@ -1,96 +0,0 @@
# Build Caching in Nano-Remix
The nano-remix package now includes intelligent build caching to improve performance by avoiding unnecessary rebuilds.
## How it Works
The caching system tracks:
- File modification timestamps
- Last build times
- Output file existence
Routes are only rebuilt when:
1. Source files have been modified since last build
2. Output files don't exist
3. Cache is explicitly disabled or forced
## Usage Examples
### Development Mode (with caching)
```typescript
import { nanoRemix } from "@workshop/nano-remix"
// Default behavior - uses intelligent caching
export default {
fetch: (req: Request) => nanoRemix(req),
}
```
### Development Mode (without caching)
```typescript
import { nanoRemix } from "@workshop/nano-remix"
// Disable caching for development if you want immediate rebuilds
export default {
fetch: (req: Request) =>
nanoRemix(req, {
disableCache: true,
}),
}
```
### Production Setup
```typescript
import { nanoRemix, preloadAllRoutes } from "@workshop/nano-remix"
// Pre-build all routes on startup for production
const server = {
async fetch(req: Request) {
return nanoRemix(req)
},
}
// Build all routes once on server startup
await preloadAllRoutes()
export default server
```
### Cache Management
```typescript
import { clearBuildCache, getBuildCacheStats } from "@workshop/nano-remix"
// Clear cache (useful for development)
clearBuildCache()
// Get cache statistics for monitoring
const stats = getBuildCacheStats()
console.log("Cache entries:", stats.length)
```
## Configuration Options
```typescript
type Options = {
routesDir?: string // Custom routes directory
distDir?: string // Custom output directory
disableCache?: boolean // Disable caching entirely
}
```
## Performance Impact
With caching enabled:
- ✅ First request to a route: Normal build time
- ✅ Subsequent requests: Near-instant response (no rebuild)
- ✅ File changes: Automatic rebuild on next request
- ✅ Production: Pre-build all routes once
This should significantly improve your server performance, especially for routes that haven't changed!

View File

@ -1,4 +1,4 @@
import { join, dirname } from "node:path"
import { join } from "node:path"
type BuildRouteOptions = {
distDir: string
@ -7,6 +7,7 @@ type BuildRouteOptions = {
force?: boolean
}
const cache = new Map<string, boolean>()
export const buildRoute = async ({ distDir, routeName, filepath, force = false }: BuildRouteOptions) => {
if (!force && !(await needsBuild(routeName, distDir))) {
return
@ -25,10 +26,9 @@ export const buildRoute = async ({ distDir, routeName, filepath, force = false }
if (exitCode !== 0) {
const stderr = await new Response(proc.stderr).text()
throw new Error(`Build process failed with exit code ${exitCode}: ${stderr}`)
} else {
cache.set(distDir + routeName, true)
}
const stdout = await new Response(proc.stdout).text()
console.log(stdout)
}
const needsBuild = async (routeName: string, distDir: string) => {
@ -38,8 +38,10 @@ const needsBuild = async (routeName: string, distDir: string) => {
try {
const outputPath = join(distDir, routeName + ".js")
const exists = await Bun.file(outputPath).exists()
const inCache = cache.get(distDir + routeName)
return !(await Bun.file(outputPath).exists())
return !exists || !inCache
} catch (error) {
return true
}

View File

@ -7,10 +7,7 @@ export type Loader<Data extends object> = (
) => Promise<Data> | Data
export type LoaderProps<T> = T extends Loader<infer R> ? Awaited<R> : never
export type Action<Data = unknown> = (
req: Request,
params: Record<string, string>
) => Promise<Response | Data>
export type Action<Data = unknown> = (req: Request, params: any) => Promise<Response | Data>
export type Head = {
title?: string

View File

@ -7,7 +7,6 @@ type Options = {
routesDir?: string
distDir?: string
publicDir?: string
disableCache?: boolean
}
let defaultPublicDir: string | undefined
@ -54,7 +53,7 @@ export const nanoRemix = async (req: Request, options: Options = {}) => {
// If the the route includes an extension it is a static file that we serve from the distDir
if (!ext) {
await buildRoute({ distDir, routeName, filepath: route.filePath, force: options.disableCache })
await buildRoute({ distDir, routeName, filepath: route.filePath })
return await renderServer(req, route)
} else {
const file = Bun.file(join(distDir, routeName + ext))

View File

@ -1,7 +1,7 @@
import KV from "@workshop/shared/kv"
import { submitAction, useAction, type Head, type LoaderProps } from "@workshop/nano-remix"
import { useCallback } from "hono/jsx/dom"
import { TodoEditor } from "@workshop/todo"
import { TodoEditor } from "../../todoEditor"
import { debounce } from "@workshop/shared/utils"
import "../../index.css"