Static Assets
How τjs handles static file serving in development and production.
Overview
Section titled “Overview”τjs serves static assets through Fastify plugins. By default, it registers @fastify/static to serve files from dist/client/, but you can customise or disable this behavior.
Default Behavior
Section titled “Default Behavior”When you create a τjs server without specifying static asset handling:
import { createServer } from "@taujs/server";
await createServer({ fastify, config, serviceRegistry, clientRoot: "./dist/client",});What happens:
- τjs registers
@fastify/staticautomatically - Points to
dist/client/directory - Serves assets under root prefix
/ - All apps share the same static file server
Result: Assets accessible at their build paths:
/app/assets/entry-client-abc123.js/admin/assets/entry-client-xyz789.jsCustom Static Configuration
Section titled “Custom Static Configuration”Override the default static plugin:
import fastifyStatic from "@fastify/static";import { createServer } from "@taujs/server";import path from "node:path";
await createServer({ fastify, config, serviceRegistry, registerStaticAssets: { plugin: fastifyStatic, options: { root: path.join(process.cwd(), "dist", "client"), prefix: "/static/", // Assets under /static/ instead of / decorateReply: false, }, },});Disabling Static Serving
Section titled “Disabling Static Serving”When using a CDN or reverse proxy to serve assets:
await createServer({ fastify, config, serviceRegistry, clientRoot: "./dist/client", registerStaticAssets: false, // Disable static middleware});Use when:
- Assets served from CDN
- Nginx/Apache serves static files
- Assets on separate domain
τjs still reads manifests from clientRoot for SSR, but doesn’t serve the files itself.
Public Directory
Section titled “Public Directory”τjs uses a project-level public/ directory:
project/├── public/│ ├── favicon.ico│ ├── robots.txt│ └── app/│ └── logo.svg└── client/ ├── app/ └── admin/During build:
- Client build: Copies
public/contents todist/client/ - SSR build: Sets
publicDir: false(no copying)
Result after build:
dist/client/├── favicon.ico├── robots.txt├── app/│ ├── logo.svg│ └── assets/└── admin/ └── assets/App-Specific Assets
Section titled “App-Specific Assets”Namespace assets by app:
public/├── app/│ ├── logo.svg│ └── favicon.ico└── admin/ ├── logo.svg └── favicon.icoReference in HTML:
<!-- Customer app --><img src="/app/logo.svg" />
<!-- Admin app --><img src="/admin/logo.svg" />CDN Integration
Section titled “CDN Integration”Upload to CDN
Section titled “Upload to CDN”After building, upload client assets:
npm run build:client
# Upload to S3aws s3 sync dist/client/ s3://my-bucket/assets/ \ --cache-control "max-age=31536000,immutable" \ --exclude "*.html"
# HTML with no-cacheaws s3 sync dist/client/ s3://my-bucket/assets/ \ --cache-control "no-cache" \ --include "*.html"Disable Local Serving
Section titled “Disable Local Serving”await createServer({ fastify, config, serviceRegistry, clientRoot: "./dist/client", // Still needed for manifests registerStaticAssets: false, // CDN serves assets});Cache Headers
Section titled “Cache Headers”Hashed assets: max-age=31536000, immutableHTML files: no-cacheOther files: no-cache (unless hashed)Reverse Proxy Setup
Section titled “Reverse Proxy Setup”Nginx Example
Section titled “Nginx Example”upstream nodejs { server localhost:3000;}
server { listen 80;
# Static assets - Nginx serves directly location ~ ^/.+/assets/ { root /app/dist/client; add_header Cache-Control "public, max-age=31536000, immutable"; }
# Try static first, then proxy to Node location / { root /app/dist/client; try_files $uri @nodejs; }
location @nodejs { proxy_pass http://nodejs; proxy_set_header Host $host; }}Configure τjs:
// Nginx handles static filesawait createServer({ fastify, config, serviceRegistry, registerStaticAssets: false,});Troubleshooting
Section titled “Troubleshooting”Assets Not Loading
Section titled “Assets Not Loading”Check static middleware is registered:
// Verify in logs[τjs] Static assets: enabledVerify files exist:
ls dist/client/app/assets/# Should show built assetsWrong MIME Types
Section titled “Wrong MIME Types”Fastify detects MIME types automatically. If incorrect:
registerStaticAssets: { plugin: fastifyStatic, options: { root: './dist/client', setHeaders: (res, path) => { if (path.endsWith('.js')) { res.setHeader('Content-Type', 'application/javascript'); } } }}