@pixengine/middleware-express
v0.3.0
Published
Express.js middleware for PixEngine image optimization
Maintainers
Readme
@pixengine/middleware-express
English | 한국어
Express.js middleware for PixEngine image optimization.
Installation
npm install @pixengine/middleware-express @pixengine/core
# or
pnpm add @pixengine/middleware-express @pixengine/core
# or
yarn add @pixengine/middleware-express @pixengine/coreQuick Start
import express from 'express';
import multer from 'multer';
import { pixEngineMiddleware } from '@pixengine/middleware-express';
import { SharpEngine } from '@pixengine/adapter-engine-sharp';
import { LocalStorage } from '@pixengine/adapter-storage-local';
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: 'http://localhost:3000/uploads',
}),
})
);
app.use('/uploads', express.static('./public/uploads'));
app.listen(3000);Response:
{
"original": {
"width": 1920,
"height": 1080,
"format": "jpeg",
"bytes": 245760
},
"variants": [
{
"key": "variants/photo_400w.webp",
"url": "http://localhost:3000/uploads/variants/photo_400w.webp",
"width": 400,
"height": 225,
"format": "webp",
"bytes": 8420
},
{
"key": "variants/photo_800w.webp",
"url": "http://localhost:3000/uploads/variants/photo_800w.webp",
"width": 800,
"height": 450,
"format": "webp",
"bytes": 24680
},
{
"key": "variants/photo_1200w.webp",
"url": "http://localhost:3000/uploads/variants/photo_1200w.webp",
"width": 1200,
"height": 675,
"format": "webp",
"bytes": 48920
}
]
}Features
- 🚀 Drop-in Express Middleware: Simple factory function pattern
- 📤 Multer Integration: Works seamlessly with multer file uploads
- 🎨 Automatic Optimization: Generates responsive image variants automatically
- 📦 Default Policy: Sensible defaults (400w, 800w, 1200w WebP images)
- ⚙️ Customizable: Override policy for custom image variants
- 🔒 Type-Safe: Full TypeScript support
- ✅ Auto JSON Response: Returns manifest directly to client
API
pixEngineMiddleware(config)
Factory function that creates an Express middleware for image optimization.
Parameters
interface PixEngineMiddlewareConfig {
engine: TransformEngine; // Required: Image processing engine
storage: StorageAdapter; // Required: Storage adapter
policy?: Policy; // Optional: Custom variant policy
}Required:
engine: TransformEngine- Image processing engine (e.g.,SharpEngine)storage: StorageAdapter- Storage adapter (e.g.,LocalStorage, S3, etc.)
Optional:
policy?: Policy- Custom policy function to define image variants
Returns
RequestHandler - Express middleware function
Default Policy
The middleware provides a default responsive image policy:
export const defaultPolicy: Policy = (ctx) => ({
variants: [
{ width: 400, format: 'webp', quality: 80 },
{ width: 800, format: 'webp', quality: 85 },
{ width: 1200, format: 'webp', quality: 90 },
],
});This generates three WebP variants at different widths, suitable for responsive web images.
Usage Examples
Basic Usage with Default Policy
import express from 'express';
import multer from 'multer';
import { pixEngineMiddleware } from '@pixengine/middleware-express';
import { SharpEngine } from '@pixengine/adapter-engine-sharp';
import { LocalStorage } from '@pixengine/adapter-storage-local';
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: 'http://localhost:3000/uploads',
}),
})
);
app.use('/uploads', express.static('./public/uploads'));
app.listen(3000);Custom Policy
import { pixEngineMiddleware } from '@pixengine/middleware-express';
import { SharpEngine } from '@pixengine/adapter-engine-sharp';
import { LocalStorage } from '@pixengine/adapter-storage-local';
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: 'http://localhost:3000/uploads',
}),
policy: (ctx) => ({
variants: [
{ width: 200, format: 'webp', quality: 75 },
{ width: 600, format: 'webp', quality: 80 },
{ width: 1000, format: 'jpeg', quality: 85 },
],
}),
})
);Context-Based Policy
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: 'http://localhost:3000/uploads',
}),
policy: (ctx) => {
// Access original image metadata
const { width, height, format } = ctx.original;
// Generate variants based on original size
if (width > 2000) {
return {
variants: [
{ width: 800, format: 'webp', quality: 80 },
{ width: 1600, format: 'webp', quality: 85 },
{ width: 2400, format: 'webp', quality: 90 },
],
};
}
// Smaller originals get fewer variants
return {
variants: [
{ width: 400, format: 'webp', quality: 80 },
{ width: 800, format: 'webp', quality: 85 },
],
};
},
})
);TypeScript Usage
import type { Request, Response, NextFunction } from 'express';
import { pixEngineMiddleware } from '@pixengine/middleware-express';
import type { PixEngineMiddlewareConfig } from '@pixengine/middleware-express';
const config: PixEngineMiddlewareConfig = {
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: 'http://localhost:3000/uploads',
}),
};
app.post('/upload', upload.single('image'), pixEngineMiddleware(config));Error Handling
The middleware handles errors automatically:
400 Bad Request
Returned when no file is uploaded:
{
"error": "No file uploaded"
}500 Internal Server Error
Returned when optimization fails:
{
"error": "Image optimization failed",
"message": "Unsupported image format"
}Custom Error Handling
You can add your own error handling middleware after the PixEngine middleware:
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware(config),
(err: Error, req: Request, res: Response, next: NextFunction) => {
console.error('Upload error:', err);
res.status(500).json({
error: 'Upload failed',
details: err.message,
});
}
);Requirements
- Node.js: >= 18.0.0
- Express: ^4.18.0 || ^5.0.0
- Multer: For file upload handling (user-provided)
- PixEngine Core: @pixengine/core
- Transform Engine: e.g., @pixengine/adapter-engine-sharp
- Storage Adapter: e.g., @pixengine/adapter-storage-local
How It Works
- User uploads file via multer middleware
- PixEngine middleware receives
req.file - Extracts image data (filename, bytes, contentType)
- Calls
optimize()with configured engine, storage, and policy - Returns manifest as JSON response automatically
Client → Multer → PixEngine Middleware → optimize() → Storage → JSON ResponseIntegration with Other Storage Adapters
AWS S3 Storage
import { S3Storage } from '@pixengine/adapter-storage-s3';
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new S3Storage({
bucket: 'my-images',
region: 'us-east-1',
baseUrl: 'https://cdn.example.com',
}),
})
);Cloudflare R2
import { R2Storage } from '@pixengine/adapter-storage-r2';
app.post(
'/upload',
upload.single('image'),
pixEngineMiddleware({
engine: new SharpEngine(),
storage: new R2Storage({
accountId: 'your-account-id',
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
bucket: 'my-images',
}),
})
);Best Practices
1. Use Memory Storage for Multer
const upload = multer({ storage: multer.memoryStorage() });This keeps uploaded files in memory, which is ideal since PixEngine processes them immediately.
2. Add File Size Limits
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 10 * 1024 * 1024, // 10MB
},
});3. Validate File Types
const upload = multer({
storage: multer.memoryStorage(),
fileFilter: (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true);
} else {
cb(new Error('Only image files are allowed'));
}
},
});4. Set Appropriate baseUrl
For production, use your CDN or domain:
storage: new LocalStorage({
baseDir: './public/uploads',
baseUrl: process.env.CDN_URL || 'https://cdn.example.com/uploads',
})5. Use Environment Variables
const config: PixEngineMiddlewareConfig = {
engine: new SharpEngine(),
storage: new LocalStorage({
baseDir: process.env.UPLOAD_DIR || './public/uploads',
baseUrl: process.env.BASE_URL || 'http://localhost:3000/uploads',
}),
};License
MIT © PixEngine Team
