Framework Integration
Learn how to integrate Photon into your Vite-based framework to enable universal server capabilities.
Overview
Photon enables frameworks to work universally across server runtimes and deployment platforms. This guide shows how to integrate Photon into your framework.
Basic Integration
1. Install Dependencies
npm install @photonjs/core @photonjs/runtime @universal-middleware/core
2. Create Photon Plugin
Create a Vite plugin that integrates Photon:
// src/vite/photonPlugin.ts
import { installPhoton } from "@photonjs/runtime/vite";
import type { Plugin } from "vite";
export function photonPlugin(): Plugin[] {
return installPhoton("your-framework", {
// Enable full Photon functionality
fullInstall: true,
// Configure code splitting (optional)
codeSplitting: {
// Disable if your framework doesn't support it
framework: false,
},
// Define universal middlewares for all entries
resolveMiddlewares() {
return "your-framework/universal-middleware";
},
// Define framework-specific entries
entries: {
standalone: {
id: "your-framework/standalone",
compositionMode: "isolated",
},
},
});
}
3. Create Universal Middleware
Define middleware using the universal middleware pattern:
// src/photon/middlewares/ssr.ts
import { enhance } from "@universal-middleware/core";
export const ssrMiddleware = enhance(
async (request: Request) => {
// Your framework's rendering logic
const html = await renderPage(request.url);
return new Response(html, {
status: 200,
headers: {
"Content-Type": "text/html",
},
});
},
{
name: "your-framework:ssr",
path: "/**",
method: "GET",
}
);
4. Export Middleware
Create entry points for your middleware:
// src/photon/entries/universal-middleware.ts
export { ssrMiddleware } from "../middlewares/ssr.js";
export { apiMiddleware } from "../middlewares/api.js";
5. Configure Package Exports
Set up conditional exports in your package.json
:
{
"exports": {
"./universal-middleware": "./dist/photon/entries/universal-middleware.js",
"./standalone": "./dist/photon/entries/standalone.js"
}
}
Advanced Patterns
Multiple Middleware Types
Create different middleware for different purposes:
- Pass information into request context
- Modify response headers
- Guard routes
- Use route parameters
- Use runtime information
Conditional Middleware Loading
Use export conditions to load middleware conditionally:
{
"exports": {
"./universal-middleware": {
"types": "./dist/universal.d.ts",
"development": {
"types": "./dist/universal.dev.d.ts",
"import": "./dist/universal.dev.js",
"default": "./dist/universal.dev.js"
},
"worker": {
"types": "./dist/universal.edge.d.ts",
"import": "./dist/universal.edge.js",
"default": "./dist/universal.edge.js"
},
"import": "./dist/universal.js",
"default": "./dist/universal.js"
}
}
}
Deployment Integration
Enable your framework users to deploy anywhere by integrating deployment adapters.
Basic Deployment Support
// src/vite/photonPlugin.ts
export function photonPlugin(options: FrameworkOptions): Plugin[] {
const plugins = installPhoton("your-framework", {
fullInstall: true,
resolveMiddlewares: () => "your-framework/universal-middleware"
});
// Add deployment adapters based on user configuration
if (options.deploy?.cloudflare) {
const { cloudflare } = await import("@photonjs/cloudflare/vite");
plugins.push(cloudflare(options.deploy.cloudflare));
}
return plugins;
}
Framework Configuration for Deployment
// Allow users to configure deployment
export interface FrameworkOptions {
deploy?: {
cloudflare?: {
entry?: string;
pages?: boolean;
};
vercel?: {
edge?: boolean;
};
netlify?: {
edge?: boolean;
};
};
}
Universal Build Output
Ensure your framework generates universal build outputs:
// src/build/index.ts
export async function buildFramework(options: BuildOptions) {
// Build client assets
await buildClient(options);
// Build server with universal middleware
await buildServer(options);
// Generate deployment-specific entries
await generateDeploymentEntries(options);
}
async function generateDeploymentEntries(options: BuildOptions) {
// Generate Cloudflare entry
if (options.deploy?.cloudflare) {
await generateCloudflareEntry(options);
}
// Generate Vercel entry
if (options.deploy?.vercel) {
await generateVercelEntry(options);
}
}
Integration Examples
Simple Framework (awesome-framework)
The example/awesome-framework
shows a minimal integration:
- Universal middleware for SSR and API handling
- Simple configuration with basic Photon setup
- Export conditions for conditional loading
Key files:
src/vite/photonPlugin.ts
- Photon integrationsrc/photon/middlewares/ssr.ts
- SSR middlewaresrc/photon/entries/
- Middleware exports
Advanced Framework (Vike)
Vike demonstrates advanced Photon integration:
- Complex middleware composition with multiple layers
- Runtime-specific optimizations for different deployment targets
- Advanced configuration with user customization options
Best Practices
Universal Middleware Design
Every handler and middleware used by Photon should respect the universal middleware pattern.
import { enhance } from "@universal-middleware/core";
// ✅ Good: Universal middleware that works everywhere
export const middleware = enhance(
async (request: Request) => {
// Use standard Web APIs
const url = new URL(request.url);
const response = await processRequest(url);
return response;
},
{ name: "framework:handler" }
);
// ❌ Avoid: Platform-specific code
export const middleware = enhance(
async (request: Request, context, runtime) => {
// Don't rely on platform-specific context
const nodeReq = runtime.req.node; // Won't work on edge
return processNodeRequest(nodeReq);
},
{ name: "framework:handler" }
);
Development vs. Production
// src/photon/entries/universal-middleware.dev.ts
import { ssrMiddleware } from "../middlewares/ssr.js";
import { loggerMiddleware } from "../middlewares/logger.js";
import { errorMiddleware } from "../middlewares/error.js";
export default [ssrMiddleware, loggerMiddleware, errorMiddleware];
// src/photon/entries/universal-middleware.prod.ts
import { ssrMiddleware } from "../middlewares/ssr.js";
import { errorMiddleware } from "../middlewares/error.js";
// No logger in production
export default [ssrMiddleware, errorMiddleware];
Testing Your Integration
TODO
Troubleshooting
TODO