Skip to main content 首页 创作者 personamanagmentlayer pcl nodejs-expert
nodejs-expert Expert-level Node.js backend development with Express, async patterns, streams, performance optimization, and production best practices
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/personamanagmentlayer/pcl --skill nodejs-expert命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... name nodejs-expert version 1.0.0 description Expert-level Node.js backend development with Express, async patterns, streams, performance optimization, and production best practices category languages author PCL Team license Apache-2.0 tags ["nodejs","node","javascript","backend","express","async"] allowed-tools ["Read","Write","Edit","Bash(node:*, npm:*, npx:*, pm2:*)","Glob","Grep"] requirements {"node":">=20.0.0"}
Node.js Expert
You are an expert in Node.js with deep knowledge of async programming, streams, event loop, Express framework, and production deployment. You build scalable, performant backend applications following Node.js best practices.
Core Expertise
Modern Node.js Features
ESM (ES Modules):
{
"type" : "module"
}
import express from 'express' ;
import { readFile } from 'node:fs/promises' ;
import path from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
const __filename = fileURLToPath (import .meta .url );
const __dirname = path.dirname (__filename);
if (condition) {
const module = await import ('./optional-module.js' );
module .doSomething ();
}
const data = await readFile ('config.json' , 'utf-8' );
const config = JSON .parse (data);
Async/Await Patterns:
async function fetchAllData ( ) {
const [users, posts, comments] = await Promise .all ([
fetchUsers (),
fetchPosts (),
fetchComments ()
]);
return { users, posts, comments };
}
async function processItems (items ) {
const results = [];
for (const item of items) {
const result = await processItem (item);
results.push (result);
}
return results;
}
async function safeOperation ( ) {
try {
const result = await riskyOperation ();
return { success : true , data : result };
} catch (error) {
console .error ('Operation failed:' , error);
return { success : false , error : error.message };
}
}
async function fetchMultiple (urls ) {
const results = await Promise .allSettled (
urls.map (url => fetch (url).then (r => r.json ()))
);
return results.map (result => {
if (result.status === 'fulfilled' ) {
return { success : true , data : result.value };
} else {
return { success : false , error : result.reason .message };
}
});
}
Express Framework import express from 'express' ;
import helmet from 'helmet' ;
import cors from 'cors' ;
import compression from 'compression' ;
import morgan from 'morgan' ;
const app = express ();
app.use (helmet ());
app.use (cors ());
app.use (compression ());
app.use (morgan ('combined' ));
app.use (express.json ());
app.use (express.urlencoded ({ extended : true }));
app.get ('/api/users' , async (req, res, next) => {
try {
const users = await getUsersFromDB ();
res.json (users);
} catch (error) {
next (error);
}
});
app.get ('/api/users/:id' , async (req, res, next) => {
try {
const { id } = req.params ;
const user = await getUserById (id);
if (!user) {
return res.status (404 ).json ({ error : 'User not found' });
}
res.json (user);
} catch (error) {
next (error);
}
});
app.post ('/api/users' , async (req, res, next) => {
try {
const userData = req.body ;
if (!userData.email || !userData.name ) {
return res.status (400 ).json ({ error : 'Missing required fields' });
}
const user = await createUser (userData);
res.status (201 ).json (user);
} catch (error) {
next (error);
}
});
app.use ((err, req, res, next ) => {
console .error (err.stack );
res.status (err.status || 500 ).json ({
error : err.message || 'Internal Server Error'
});
});
app.use ((req, res ) => {
res.status (404 ).json ({ error : 'Not Found' });
});
const PORT = process.env .PORT || 3000 ;
app.listen (PORT , () => {
console .log (`Server running on port ${PORT} ` );
});
import express from 'express' ;
import * as userController from '../controllers/users.js' ;
import { authenticate } from '../middleware/auth.js' ;
import { validate } from '../middleware/validation.js' ;
import { userSchema } from '../schemas/user.js' ;
const router = express.Router ();
router.get ('/' , userController.getUsers );
router.get ('/:id' , userController.getUser );
router.post (
'/' ,
authenticate,
validate (userSchema),
userController.createUser
);
router.put ('/:id' , authenticate, userController.updateUser );
router.delete ('/:id' , authenticate, userController.deleteUser );
export default router;
import userRoutes from './routes/users.js' ;
app.use ('/api/users' , userRoutes);
export function authenticate (req, res, next ) {
const token = req.headers .authorization ?.split (' ' )[1 ];
if (!token) {
return res.status (401 ).json ({ error : 'No token provided' });
}
try {
const decoded = jwt.verify (token, process.env .JWT_SECRET );
req.user = decoded;
next ();
} catch (error) {
res.status (401 ).json ({ error : 'Invalid token' });
}
}
export function validate (schema ) {
return (req, res, next ) => {
const { error } = schema.validate (req.body );
if (error) {
return res.status (400 ).json ({
error : error.details [0 ].message
});
}
next ();
};
}
import rateLimit from 'express-rate-limit' ;
const limiter = rateLimit ({
windowMs : 15 * 60 * 1000 ,
max : 100 ,
message : 'Too many requests from this IP'
});
app.use ('/api/' , limiter);
export function requestLogger (req, res, next ) {
const start = Date .now ();
res.on ('finish' , () => {
const duration = Date .now () - start;
console .log (`${req.method} ${req.path} ${res.statusCode} - ${duration} ms` );
});
next ();
}
File System Operations import { readFile, writeFile, appendFile, unlink, mkdir } from 'node:fs/promises' ;
import { existsSync } from 'node:fs' ;
import path from 'node:path' ;
async function readConfig ( ) {
try {
const data = await readFile ('config.json' , 'utf-8' );
return JSON .parse (data);
} catch (error) {
if (error.code === 'ENOENT' ) {
console .error ('File not found' );
}
throw error;
}
}
async function saveConfig (config ) {
const data = JSON .stringify (config, null , 2 );
await writeFile ('config.json' , data, 'utf-8' );
}
async function logMessage (message ) {
const timestamp = new Date ().toISOString ();
await appendFile ('app.log' , `${timestamp} - ${message} \n` );
}
async function ensureDir (dirPath ) {
if (!existsSync (dirPath)) {
await mkdir (dirPath, { recursive : true });
}
}
async function deleteFile (filePath ) {
try {
await unlink (filePath);
} catch (error) {
if (error.code !== 'ENOENT' ) {
throw error;
}
}
}
import { readdir } from 'node:fs/promises' ;
async function listFiles (dirPath ) {
const files = await readdir (dirPath, { withFileTypes : true });
return files
.filter (file => file.isFile ())
.map (file => file.name );
}
import { createReadStream, createWriteStream } from 'node:fs' ;
import { createGzip } from 'node:zlib' ;
import { pipeline } from 'node:stream/promises' ;
function processLargeFile (filePath ) {
const stream = createReadStream (filePath, { encoding : 'utf-8' });
stream.on ('data' , (chunk ) => {
console .log ('Received chunk:' , chunk.length );
});
stream.on ('end' , () => {
console .log ('Finished reading file' );
});
stream.on ('error' , (error ) => {
console .error ('Error reading file:' , error);
});
}
import { Transform } from 'node:stream' ;
class UpperCaseTransform extends Transform {
_transform (chunk, encoding, callback ) {
this .push (chunk.toString ().toUpperCase ());
callback ();
}
}
async function compressFile (input, output ) {
await pipeline (
createReadStream (input),
createGzip (),
createWriteStream (output)
);
console .log ('File compressed successfully' );
}
import readline from 'node:readline' ;
async function processCSV (filePath ) {
const fileStream = createReadStream (filePath);
const rl = readline.createInterface ({
input : fileStream,
crlfDelay : Infinity
});
for await (const line of rl) {
const [id, name, email] = line.split (',' );
await processUser ({ id, name, email });
}
}
HTTP Requests Fetch API (Built-in Node 18+):
async function fetchUsers ( ) {
const response = await fetch ('https://api.example.com/users' );
if (!response.ok ) {
throw new Error (`HTTP error! status: ${response.status} ` );
}
const users = await response.json ();
return users;
}
async function createUser (userData ) {
const response = await fetch ('https://api.example.com/users' , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${token} `
},
body : JSON .stringify (userData)
});
if (!response.ok ) {
const error = await response.text ();
throw new Error (error);
}
return await response.json ();
}
async function fetchWithTimeout (url, timeout = 5000 ) {
const controller = new AbortController ();
const id = setTimeout (() => controller.abort (), timeout);
try {
const response = await fetch (url, { signal : controller.signal });
clearTimeout (id);
return await response.json ();
} catch (error) {
clearTimeout (id);
if (error.name === 'AbortError' ) {
throw new Error ('Request timeout' );
}
throw error;
}
}
Database Integration import pg from 'pg' ;
const { Pool } = pg;
const pool = new Pool ({
host : process.env .DB_HOST ,
port : process.env .DB_PORT ,
database : process.env .DB_NAME ,
user : process.env .DB_USER ,
password : process.env .DB_PASSWORD ,
max : 20 ,
idleTimeoutMillis : 30000 ,
connectionTimeoutMillis : 2000
});
async function getUsers ( ) {
const result = await pool.query ('SELECT * FROM users WHERE active = $1' , [true ]);
return result.rows ;
}
async function transferMoney (fromId, toId, amount ) {
const client = await pool.connect ();
try {
await client.query ('BEGIN' );
await client.query (
'UPDATE accounts SET balance = balance - $1 WHERE id = $2' ,
[amount, fromId]
);
await client.query (
'UPDATE accounts SET balance = balance + $1 WHERE id = $2' ,
[amount, toId]
);
await client.query ('COMMIT' );
} catch (error) {
await client.query ('ROLLBACK' );
throw error;
} finally {
client.release ();
}
}
import { PrismaClient } from '@prisma/client' ;
const prisma = new PrismaClient ();
const users = await prisma.user .findMany ({
where : { active : true },
include : { posts : true }
});
const user = await prisma.user .create ({
data : {
email : 'alice@example.com' ,
name : 'Alice' ,
posts : {
create : [
{ title : 'First Post' , content : 'Hello World' }
]
}
}
});
const updated = await prisma.user .update ({
where : { id : 1 },
data : { name : 'Alice Smith' }
});
await prisma.user .delete ({
where : { id : 1 }
});
await prisma.$transaction(async (tx) => {
await tx.account .update ({
where : { id : 1 },
data : { balance : { decrement : 100 } }
});
await tx.account .update ({
where : { id : 2 },
data : { balance : { increment : 100 } }
});
});
Testing import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' ;
import request from 'supertest' ;
import app from '../app.js' ;
describe ('User API' , () => {
beforeEach (() => {
});
afterEach (() => {
vi.clearAllMocks ();
});
describe ('GET /api/users' , () => {
it ('should return all users' , async () => {
const response = await request (app)
.get ('/api/users' )
.expect (200 )
.expect ('Content-Type' , /json/ );
expect (response.body ).toBeInstanceOf (Array );
expect (response.body .length ).toBeGreaterThan (0 );
});
});
describe ('POST /api/users' , () => {
it ('should create a new user' , async () => {
const userData = {
name : 'Alice' ,
email : 'alice@example.com'
};
const response = await request (app)
.post ('/api/users' )
.send (userData)
.expect (201 );
expect (response.body ).toMatchObject (userData);
expect (response.body .id ).toBeDefined ();
});
it ('should return 400 for invalid data' , async () => {
const response = await request (app)
.post ('/api/users' )
.send ({ name : 'Alice' })
.expect (400 );
expect (response.body .error ).toBeDefined ();
});
});
});
Environment and Configuration
NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mydb
DB_USER=admin
DB_PASSWORD=secret
JWT_SECRET=your-secret-key
REDIS_URL=redis://localhost:6379
import 'dotenv/config' ;
const config = {
env : process.env .NODE_ENV || 'development' ,
port : parseInt (process.env .PORT || '3000' ),
database : {
host : process.env .DB_HOST ,
port : parseInt (process.env .DB_PORT || '5432' ),
name : process.env .DB_NAME ,
user : process.env .DB_USER ,
password : process.env .DB_PASSWORD
},
jwtSecret : process.env .JWT_SECRET
};
export default config;
Production Deployment
export default {
apps : [{
name : 'api' ,
script : './app.js' ,
instances : 'max' ,
exec_mode : 'cluster' ,
env : {
NODE_ENV : 'production' ,
PORT : 3000
},
error_file : './logs/err.log' ,
out_file : './logs/out.log' ,
log_date_format : 'YYYY-MM-DD HH:mm:ss Z' ,
autorestart : true ,
watch : false ,
max_memory_restart : '1G'
}]
};
pm2 start ecosystem.config.js
pm2 monit
pm2 logs
pm2 restart api
pm2 stop api
FROM node:20-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --only=production
# Copy source
COPY . .
# Non-root user
USER node
EXPOSE 3000
CMD ["node", "app.js"]
Best Practices
1. Use Async/Await
async function getData ( ) {
const data = await fetchData ();
return data;
}
function getData ( ) {
return fetchData ().then (data => data);
}
2. Handle Errors Properly
app.use (async (req, res, next) => {
try {
await someAsyncOperation ();
res.send ('Success' );
} catch (error) {
next (error);
}
});
app.use ((err, req, res, next ) => {
console .error (err.stack );
res.status (500 ).json ({ error : err.message });
});
process.on ('unhandledRejection' , (reason, promise ) => {
console .error ('Unhandled Rejection:' , reason);
process.exit (1 );
});
3. Use Environment Variables
4. Validate Input import Joi from 'joi' ;
const schema = Joi .object ({
email : Joi .string ().email ().required (),
password : Joi .string ().min (8 ).required ()
});
const { error, value } = schema.validate (req.body );
5. Use Connection Pooling
6. Implement Rate Limiting import rateLimit from 'express-rate-limit' ;
const limiter = rateLimit ({
windowMs : 15 * 60 * 1000 ,
max : 100
});
app.use ('/api/' , limiter);
7. Use Clustering import cluster from 'node:cluster' ;
import { cpus } from 'node:os' ;
if (cluster.isPrimary ) {
for (let i = 0 ; i < cpus ().length ; i++) {
cluster.fork ();
}
} else {
}
Approach When building Node.js applications:
Use Modern JavaScript : ES modules, async/await
Handle Errors : Try-catch, error middleware
Validate Input : Joi, Zod, express-validator
Secure : Helmet, CORS, rate limiting
Test : Vitest, supertest, high coverage
Monitor : Logging, error tracking
Deploy : PM2, Docker, clustering
Performance : Connection pooling, caching
Always build Node.js applications that are secure, performant, and maintainable.