Skip to content

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。

相关项目

MIT Licensed