Micri Microservices Framework
Micri is a lightweight, asynchronous HTTP microservices library for Node.js, currently at version 4.5.1. It provides a minimal yet high-performance foundation for building single-purpose HTTP functions, emphasizing explicit control over request handling. Key differentiators include its small codebase (~500 lines), opt-in JSON parsing for speed, and strong integration with `async`/`await` patterns for easy asynchronous operations. Unlike larger frameworks, Micri deliberately avoids middleware, requiring developers to explicitly declare and handle all dependencies within their request handlers. Its standard HTTP approach and agility make it suitable for containerized and serverless deployments. The project has a stable release cadence, with recent major updates addressing Node.js compatibility and core feature enhancements.
Common errors
-
ReferenceError: require is not defined in ES module scope
cause Attempting to use CommonJS `require()` syntax within an ES module context (e.g., in a file with `.mjs` extension or when `"type": "module"` is set in `package.json`).fixReplace all `const { symbol } = require('micri');` statements with `import { symbol } from 'micri';` for Micri imports in your ES module files. -
TypeError: res.send is not a function
cause Attempting to use convenience methods like `res.send()` or `res.json()` that are common in frameworks like Express, but are not part of Micri's native `http.ServerResponse` object.fixMicri handlers operate directly with native Node.js `http.ServerResponse`. To send data, either return a string, Buffer, or Stream from your handler, or use `res.end()` for direct manipulation. For example, `return 'Hello World';` or `res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ message: 'Hello' })); return;`. -
Error: Request body already consumed
cause Invoking `buffer(req)`, `text(req)`, or `json(req)` more than once for the same incoming HTTP request stream.fixCall body parsing functions only once per request. Store the result in a variable and reuse it throughout your handler to access the parsed body data. For example, `const requestBody = await json(req);`
Warnings
- breaking Micri v4.0.0 dropped support for Node.js 10.x. All projects using Micri v4 and above must run on Node.js 12.0.0 or a newer compatible version.
- gotcha Micri is intentionally designed without a middleware system, contrasting with frameworks like Express. All request-specific logic (e.g., authentication, logging, explicit body parsing) must be handled within your core handler functions or by wrapping them.
- gotcha Request body parsing (for JSON, URL-encoded forms, text, or binary buffers) is not automatic. Developers must explicitly call `buffer(req)`, `text(req)`, or `json(req)` to consume the incoming request body.
- gotcha When using Micri's built-in router, the order of routes provided as arguments to the `router()` function determines their priority. The first matching route in the list will handle the request.
Install
-
npm install micri -
yarn add micri -
pnpm add micri
Imports
- serve
const server = micri(...);
import { serve } from 'micri'; - { buffer, text, json }
import * as bodyParser from 'micri/body';
import { buffer, text, json } from 'micri'; - Router
import router from 'micri/router';
import { Router } from 'micri'; - Router.router
import { router } from 'micri';import { Router } from 'micri'; const myRouter = Router.router(...); - on
import { on } from 'micri';
Quickstart
import { serve } from 'micri';
import { ServerResponse, IncomingMessage, Server } from 'http';
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
interface CustomRequest extends IncomingMessage {
// Micri handlers receive native Node.js http.IncomingMessage
// You can extend it for custom properties if needed.
}
const handler = async (req: CustomRequest, res: ServerResponse): Promise<string> => {
// Simulate an asynchronous operation, e.g., database call or external API fetch
await sleep(500);
// Micri handlers can return a string, Buffer, or Stream directly to send as the response body.
return `Hello from Micri! You accessed: ${req.url}`;
};
const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;
const server: Server = serve(handler);
server.listen(PORT, () => {
console.log(`Micri server listening on http://localhost:${PORT}`);
console.log('Try opening http://localhost:3000/hello or http://localhost:3000/world in your browser.');
});