- Introduction
- Installation
- Recommendations
- Requirements
- Options
- Comparison
- Usage
- Hooks
- Middlewares
- Handlers
- Router
- Request
- Response
- Docker
[E]
- Known bugs
- IDE Support
- Benchmarks
[I]
The Ultimate version is specially made for sponsors and includes a lot of re-writes than old codebase, makes your code much stable. Includes new things such as
- Router finder & matcher
- Hooks
- Batches responses
- express API compatibility polyfill
and makes your development easier & cost-effective. It's fastest yet in nanoexpress family
npm install nanoexpress/ultimate
# or
npm install nanoexpress/ultimate#v1.2.7
# or
npm install https://github.com/nanoexpress/ultimate/archive/refs/heads/master.zip
# or
npm install https://github.com/nanoexpress/ultimate/archive/refs/tags/v1.2.7.zip
- Enabling
node --enable-source-maps
flag 1[E]
- Enabling
node --expose-gc
flag 2[E]
- Using Ubuntu (20.04+) image on Docker or on host-machine if possible
- Do not use CentOS or Alpine images on Docker or host-machine please
Use either
https
orhttp
, not both of them
Name | Default | Description |
---|---|---|
https |
- | Runs server with built-in HTTPS server with own configuration |
http |
- | Runs server with built-in HTTP server with own configuration |
ignoreTrailingSlash |
true |
Makes routes / slashes insensitive when enabled |
enableExpressCompatibility |
false |
Enables compatibility to express middlewares |
poolSize |
10 |
Uses caching of instances to improve performance and optimize memory |
console |
console |
Console instance, can be replaced logger |
json_spaces |
- | JSON encoding and making it prettifies |
json_replacer |
- | JSON and can be replaced from default JSON.stringify behavior |
responseMode |
queue |
Makes response batched (cork), immediate or queued |
Feature | nanoexpress | pro-slim | ultimate |
---|---|---|---|
Performance | Best | Best | Better |
Stability | Good | Best | Better |
Express API | Good | Good | Better |
Caching | - | - | Best |
Memory optimizer | - | - | Better |
Garbage Collector | - | Better | Better |
Dev Debugger | - | - | Available |
Hooks | - | - | Available |
Batching | - | - | Available |
Customizable | Good | - | Better |
Route Finder | v8.x |
- | Better |
IDE Support | Good | Best | Better |
TypeScript | Good | Good | Better + Tools |
JSDoc comments | - | Best | Better |
Target user | Anyone | Commercial | Enterprise |
Price | Free | Free for Open-Source | Free for Open-Source |
License | Apache-2.0 | GPL-3.0 | GPL-3.0 |
Feature | express | nanoexpress | ultimate |
---|---|---|---|
Middlewares | Better | Good | Best |
Async routes | - | Good | Better |
Validation | Middleware | Middleware | Middleware |
Serialization | Middleware | Middleware | Middleware |
Swagger | Middleware | Middleware | Middleware |
Performance | 1x |
6x |
8x |
Hooks | - | - | Available |
TS+JSDoc | Better | Good | Better + Tools |
Price | Free | Free | Free for Open-Source |
License | MIT | Apache-2.0 | GPL-3.0 |
import nanoexpress from '@nanoexpress/ultimate/esm';
const app = nanoexpress();
app.get('/', async () => {
return { status: 'ok' };
});
await app.listen(8000);
const nanoexpress = require('@nanoexpress/ultimate');
const app = nanoexpress();
app.get('/', async () => {
return { status: 'ok' };
});
app.listen(8000);
import nanoexpress, { useEffect } from '@nanoexpress/ultimate/esm';
const app = nanoexpress();
app.get('/', async (req) => {
useEffect(() => {
// this effect was initilized once for all connections
// about memoize & caching don't worry
}, []);
useEffect(() => {
console.log('logging user actions once by client id');
// you can send server, initialize websocket or more actions
// the hooks is similar to you seen in React library
}, [req.headers['x-client-id']]);
return { status: 'ok' };
});
await app.listen(8000);
Name | Description | Example |
---|---|---|
useEffect |
Logic implementation hook | useEffect(() => console.log('router called'), [req.id]) |
useMemo |
Memorizing computational logics | const result = useMemo(() => compute_something(1_000_000), []) |
useCallback |
Handler memorizing | const runLogic = useCallback(() => do_logic(), []) |
useRef |
Reference memorizing | const ref = useRef(null) |
useState |
State management | const [state, setState] = useState(0) |
See static serve [E]
middleware specially
built for nanoexpress family
or go here [I]
for more middlewares
app.setNotFoundHandler(req: HttpRequest, res: HttpResponse)
app.setErrorHandler(error: Error, req: HttpRequest, res: HttpResponse)
These handlers own default values, so you should not worry about setting them at starting code
The router class is almost same as express and does like express middleware layer stacking, finding & matching happens inside router finder logic
To believe me see some example yourself
import nanoexpress from '@nanoexpress/ultimate';
const app = nanoexpress();
const router = nanoexpress.Router();
app.use('/foo', router);
router.get('/', async () => {
return { status: 'ok' };
});
await app.listen(8000);
// now go-to `http://localhost:8000/foo` and you should see json `{status: 'ok'}`
- headers
- params
- query
- body
app.get('/secret', (req) => {
const { authorization } = req.headers;
});
app.get('/user/:id/login', async (req) => {
const { id } = req.params;
const result = await db.getUser(id);
// do something...
});
// /user?token=123
app.get('/user', async (req) => {
const { token } = req.query;
const result = await jwt.verifyToken(token);
// do something...
});
app.use(bodyParser());
app.post('/user', async (req) => {
const { username, password } = req.body;
// You can use db.createUser(req.body), but this may cause side-effects
const result = await db.createUser({ username, password });
// do something...
});
app.use(bodyParser());
app.post('/user', async (req, res) => {
req.pipe(res);
});
and now try request with body as some text content
app.use(bodyParser());
app.use(cookieParser());
app.post('/user', async (req) => {
const { userId } = req.cookies;
// You can use db.createUser(req.body), but this may cause side-effects
const isUserLoggedIn = await dbHelper.checkUser(userId);
// do something...
});
And Upload [E]
example
app.get('/is_logged', async (req, res) => {
const status = res.hasCookie('userId') ? 'success' : 'error';
return res.send({ status });
});
app.get('/user/:id/login', async (req, res) => {
const { id } = req.params;
const result = await db.getUser(id);
return res.redirect(`/user/${id}/`);
});
app.get('/user/:id/login', async (req, res) => {
const file = fs.createReadStream('some_video.mp4');
file.pipe(res);
// or res.stream(file)
});
File should be on the same path where JS file is, or you can try Absolute path for stream/sendFile
app.get('/video.mp4', async (req, res) => {
return res.sendFile('video.mp4');
});
- HTTP Pipeline not working properly
[E]
- If "Invalid access of discarded ..." happens, report ASAP to library author to get fix
IDE Support was provided by TypeScript typings and JSDoc comments with source-mapping for improved debugging, you should not worry about this