快速上手:如何极简搭建一个纯净的 Node.js 项目

1,435 阅读5分钟

前言

最近在学习 langchain.js,使用 Deno 和 Jupyter Notebook 的方式调试代码。调试体验非常不好,Deno 提供的 js/ts Kernel 支持经常崩溃。无奈之下,选择自己搭建一个 Node 环境来调试代码。

在日常的 Web 开发中,我们经常需要测试 Node.js 代码。如果使用 KoaExpressNestJS 等框架的脚手架来创建项目,往往会觉得过于冗余,还需要适应不同框架的编码规范。那么,有没有一种方法可以快速搭建一个简洁的 Node.js 开发环境,用于简单的代码验证或 demo 开发呢?本文将带你一步步搭建一个支持热更新、代码格式化、代码检查和单元测试的 Node.js 开发环境。

1. 初始化项目

首先,我们需要创建一个新的项目目录并初始化一个 Node.js 项目:

mkdir node-ts-project
cd node-ts-project
npm init -y

这将生成一个默认的 package.json 文件。

2. 安装 TypeScript 和开发工具

接下来,我们需要安装 TypeScript 及其相关工具:

npm install --save-dev typescript ts-node ts-node-dev @types/node
  • typescript: TypeScript 编译器
  • ts-node: 用于直接运行 TypeScript 代码
  • ts-node-dev: 用于开发时运行 TypeScript 代码并支持热更新
  • @types/node: Node.js 的 TypeScript 类型定义

3. 配置 TypeScript

在项目根目录下创建 tsconfig.json 文件,并添加以下配置:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

4. 创建项目结构

在项目根目录下创建 src 目录,并在其中创建 index.ts 文件:

import { createServer, IncomingMessage, ServerResponse } from 'http';
import { parse } from 'url';

const server = createServer((req: IncomingMessage, res: ServerResponse) => {
  const parsedUrl = parse(req.url || '', true);
  const { pathname } = parsedUrl;

  if (pathname === '/api/hello' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Hello, world!' }));
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Not Found' }));
  }
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

5. 添加启动脚本

package.json 中添加以下脚本:

"scripts": {
  "start": "ts-node-dev src/index.ts",
}

一个支持 Typescript 的 Node 开发环境,就已经搭建好了。只需要 npm run start 就可以在浏览器中调用接口了

image.png

如果你还想要更好的开发体验,我们继续优化

6. 添加 ESLint 和 Prettier

为了保持代码质量和一致的代码风格,我们需要安装 ESLint 和 Prettier:

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier eslint-plugin-prettier prettier

在项目根目录下创建 .eslintrc.js 文件,并添加以下配置:

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  rules: {
    'prettier/prettier': 'error',
  },
  env: {
    node: true,
    es6: true,
  },
};

在项目根目录下创建 .prettierrc 文件,并添加以下配置:

{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 80,
  "tabWidth": 2
}

到这,整个项目就已经相对完整了。如果你的 vscode 中已经配置了保存后自动格式化的功能,那就能直接看到效果了。为了使项目更加的完整,我们把 单元测试(估计大部分人都没有用的习惯)、READMEgit 都加上

7. 添加单元测试

为了确保代码的正确性,我们需要添加单元测试支持。我们选择 Jest 作为测试框架:

npm install --save-dev jest ts-jest @types/jest

在项目根目录下创建 jest.config.js 文件,并添加以下配置:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  testMatch: ['**/tests/**/*.test.ts'],
};

在项目根目录下创建 tests 目录,并在其中创建 index.test.ts 文件:

import { createServer, IncomingMessage, ServerResponse } from 'http';
import { parse } from 'url';

const server = createServer((req: IncomingMessage, res: ServerResponse) => {
  const parsedUrl = parse(req.url || '', true);
  const { pathname } = parsedUrl;

  if (pathname === '/api/hello' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Hello, world!' }));
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Not Found' }));
  }
});

describe('Server', () => {
  it('should return Hello, world! for GET /api/hello', (done) => {
    const req = new IncomingMessage(null);
    req.url = '/api/hello';
    req.method = 'GET';

    const res = new ServerResponse(req);
    res.on('finish', () => {
      expect(res.statusCode).toBe(200);
      expect(res.getHeader('Content-Type')).toBe('application/json');
      done();
    });

    server.emit('request', req, res);
  });

  it('should return Not Found for other routes', (done) => {
    const req = new IncomingMessage(null);
    req.url = '/api/unknown';
    req.method = 'GET';

    const res = new ServerResponse(req);
    res.on('finish', () => {
      expect(res.statusCode).toBe(404);
      expect(res.getHeader('Content-Type')).toBe('application/json');
      done();
    });

    server.emit('request', req, res);
  });
});

8. 添加启动和测试脚本

package.json 中添加以下脚本:

"scripts": {
  "start": "ts-node-dev src/index.ts",
  "format": "prettier --write \"src/**/*.ts\"",
  "lint": "eslint \"src/**/*.{ts,js}\"",
  "test": "jest"
}

9. 创建 .gitignore 文件

在项目根目录下创建一个 .gitignore 文件,忽略不需要提交到版本控制的文件和目录:

# Node modules
node_modules

# Build output
dist

# TypeScript cache
*.tsbuildinfo

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# OS-specific files
.DS_Store
Thumbs.db

# Editor directories and files
.vscode
.idea
*.suo
*.ntvs*
*.njsproj
*.sln

10. 创建 README.md 文件

在项目根目录下创建一个 README.md 文件,描述项目的用途和使用方法:

# Node TypeScript Project

这是一个使用 TypeScript 编写的简单 Node.js 项目,支持热更新、代码格式化、代码检查和单元测试。

## 特性

- 使用 TypeScript 编写
- 支持热更新(使用 `ts-node-dev`- 代码格式化(使用 Prettier)
- 代码检查(使用 ESLint)
- 单元测试(使用 Jest)

## 安装

首先,克隆项目并安装依赖:

```sh
git clone <your-repo-url>
cd node-ts-project
npm install

使用

启动开发服务器

npm start

服务器将会在 http://localhost:3000 上运行。

格式化代码

npm run format

运行 ESLint 检查

npm run lint

运行单元测试

npm test

项目结构

node-ts-project/
├── src/
│   └── index.ts
├── tests/
│   └── index.test.ts
├── .eslintrc.js
├── .eslintignore
├── .prettierrc
├── .prettierignore
├── .gitignore
├── jest.config.js
├── README.md
├── package.json
├── tsconfig.json
└── node_modules/

总结

通过以上步骤,我们成功搭建了一个现代化的 Node.js 开发环境,支持 TypeScript、热更新、代码格式化、代码检查和单元测试,且不依赖任何的框架,代码十分简单、容易上手。这种开发环境可以用于快速验证代码逻辑,编写 Demo,不仅提高了开发效率,还能确保代码质量和一致性。