Node.js 开发笔记
Node.js 服务端开发和工具链建设笔记。
文件操作
基于 node-kit 的开发经验。
fs 模块增强
ts
import { fs } from 'node-kit'
// 确保目录存在
await fs.ensureDir('./output')
// 确保文件存在
await fs.ensureFile('./output/log.txt')
// 读取 JSON
const data = await fs.readJson('./config.json')
// 写入 JSON
await fs.writeJson('./config.json', data, { spaces: 2 })
// 复制目录
await fs.copy('./src', './dist')
// 删除目录
await fs.remove('./temp')
// 空目录
await fs.emptyDir('./output')路径处理
ts
import { path } from 'node-kit'
// 获取绝对路径
const absolute = path.resolve('./src')
// 获取相对路径
const relative = path.relative('/a/b', '/a/c')
// 获取用户目录
import { userdir } from 'userdir'
const home = userdir()
// macOS: /Users/username
// Windows: C:\Users\username
// Linux: /home/username文件监听
ts
import { watch } from 'node-kit'
watch('./src', (event, filename) => {
console.log(`${event}: ${filename}`)
})进程管理
子进程执行
ts
import { exec, spawn } from 'node-kit'
// 执行命令
const { stdout, stderr } = await exec('npm run build')
// 流式执行
const child = spawn('npm', ['run', 'dev'])
child.stdout.on('data', (data) => console.log(data.toString()))进程信号
ts
// 优雅退出
process.on('SIGTERM', () => {
console.log('Received SIGTERM')
server.close(() => process.exit(0))
})
process.on('SIGINT', () => {
console.log('Received SIGINT (Ctrl+C)')
server.close(() => process.exit(0))
})HTTP 服务
Express
基于 h5api:
ts
import express from 'express'
const app = express()
// 中间件
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// 路由
app.get('/api/users', (req, res) => {
res.json({ users: [] })
})
app.post('/api/users', (req, res) => {
const { name } = req.body
res.json({ id: 1, name })
})
// 错误处理
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message })
})
app.listen(3000)Koa
基于 h5api-koa:
ts
import Koa from 'koa'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'
const app = new Koa()
const router = new Router()
app.use(bodyParser())
router.get('/api/users', async (ctx) => {
ctx.body = { users: [] }
})
router.post('/api/users', async (ctx) => {
ctx.body = { id: 1, name: ctx.request.body.name }
})
app.use(router.routes())
app.listen(3000)Egg.js
基于 egg-nuxt-tool:
ts
// config/plugin.js
exports.nuxtTool = {
enable: true,
package: 'egg-nuxt-tool'
}
// config/config.default.js
config.nuxtTool = {
srcDir: './app/web'
}HTTP 客户端
axios-series
axios-series 提供序列化返回:
ts
import { createAxios } from 'axios-series'
const api = createAxios({
baseURL: '/api',
timeout: 10000
})
// 返回 { data, error }
const { data, error } = await api.get('/users')
if (error) {
console.error(error)
return
}
console.log(data)并发控制
axios-ex 提供并发控制:
ts
import AxiosEx from 'axios-ex'
const http = new AxiosEx({
maxConcurrent: 5,
maxRetry: 3,
retryDelay: 1000
})
// 请求会自动排队和重试
await http.get('/api/data')日志系统
ts
import { logger } from 'node-kit'
// 不同级别
logger.info('Server started')
logger.warn('Memory usage high')
logger.error('Connection failed')
// 格式化输出
logger.info('Request: %s %s', method, path)CLI 开发
命令行参数
ts
import { parseArgs } from 'node-kit'
const args = parseArgs(process.argv.slice(2))
console.log(args)
// { _: [], '--port': 3000 }用户交互
ts
import { prompt } from 'node-kit'
const answer = await prompt({
type: 'input',
name: 'name',
message: '项目名称:'
})终端样式
使用 xterm-style:
ts
import { colors, symbols } from 'xterm-style'
console.log(colors.green('成功!'))
console.log(colors.red('失败!'))
console.log(symbols.success, '完成')工具发布
Package 配置
json
{
"name": "my-tool",
"version": "1.0.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"bin": {
"my-tool": "./bin/cli.js"
}
}Shebang
CLI 入口文件添加 shebang:
js
#!/usr/bin/env node
import { program } from 'commander'
program.parse()使用 rollup-plugin-replace-shebang 处理 shebang。
相关项目
- node-kit - Node.js 工具集
- js-cool - JS/TS 工具库
- axios-series - Axios 扩展
- h5api - 前端常用接口