nodejs-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Node.js Development Guidelines

Node.js 开发指南

You are an expert in Node.js development with TypeScript, covering various frameworks and patterns.
您是一名精通 TypeScript 的 Node.js 开发专家,熟悉各类框架与开发模式。

Payload CMS with Next.js

结合 Next.js 使用 Payload CMS

Project Setup

项目结构

project/
├── src/
│   ├── app/              # Next.js app directory
│   ├── collections/      # Payload collections
│   ├── blocks/          # Custom blocks
│   ├── fields/          # Custom fields
│   └── access/          # Access control functions
├── payload.config.ts    # Payload configuration
└── next.config.js       # Next.js configuration
project/
├── src/
│   ├── app/              # Next.js app directory
│   ├── collections/      # Payload collections
│   ├── blocks/          # Custom blocks
│   ├── fields/          # Custom fields
│   └── access/          # Access control functions
├── payload.config.ts    # Payload configuration
└── next.config.js       # Next.js configuration

Collection Definition

集合定义

typescript
import { CollectionConfig } from 'payload/types';

const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
  },
  access: {
    read: () => true,
    create: ({ req: { user } }) => Boolean(user),
    update: ({ req: { user } }) => Boolean(user),
    delete: ({ req: { user } }) => Boolean(user),
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'content',
      type: 'richText',
    },
    {
      name: 'publishedDate',
      type: 'date',
    },
  ],
};

export default Posts;
typescript
import { CollectionConfig } from 'payload/types';

const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
  },
  access: {
    read: () => true,
    create: ({ req: { user } }) => Boolean(user),
    update: ({ req: { user } }) => Boolean(user),
    delete: ({ req: { user } }) => Boolean(user),
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'content',
      type: 'richText',
    },
    {
      name: 'publishedDate',
      type: 'date',
    },
  ],
};

export default Posts;

API Routes

API 路由

typescript
// app/api/posts/route.ts
import { getPayloadClient } from '@/lib/payload';

export async function GET() {
  const payload = await getPayloadClient();
  const posts = await payload.find({
    collection: 'posts',
    limit: 10,
  });
  return Response.json(posts);
}
typescript
// app/api/posts/route.ts
import { getPayloadClient } from '@/lib/payload';

export async function GET() {
  const payload = await getPayloadClient();
  const posts = await payload.find({
    collection: 'posts',
    limit: 10,
  });
  return Response.json(posts);
}

Vue.js with TypeScript

Vue.js + TypeScript 开发

Component Structure

组件结构

vue
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

interface User {
  id: number;
  name: string;
  email: string;
}

const props = defineProps<{
  userId: number;
}>();

const emit = defineEmits<{
  (e: 'update', user: User): void;
}>();

const user = ref<User | null>(null);
const isLoading = ref(false);

const displayName = computed(() => user.value?.name ?? 'Unknown');

async function fetchUser() {
  isLoading.value = true;
  try {
    const response = await fetch(`/api/users/${props.userId}`);
    user.value = await response.json();
  } finally {
    isLoading.value = false;
  }
}

onMounted(fetchUser);
</script>

<template>
  <div v-if="isLoading">Loading...</div>
  <div v-else-if="user">
    <h2>{{ displayName }}</h2>
    <p>{{ user.email }}</p>
  </div>
</template>
vue
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

interface User {
  id: number;
  name: string;
  email: string;
}

const props = defineProps<{
  userId: number;
}>();

const emit = defineEmits<{
  (e: 'update', user: User): void;
}>();

const user = ref<User | null>(null);
const isLoading = ref(false);

const displayName = computed(() => user.value?.name ?? 'Unknown');

async function fetchUser() {
  isLoading.value = true;
  try {
    const response = await fetch(`/api/users/${props.userId}`);
    user.value = await response.json();
  } finally {
    isLoading.value = false;
  }
}

onMounted(fetchUser);
</script>

<template>
  <div v-if="isLoading">Loading...</div>
  <div v-else-if="user">
    <h2>{{ displayName }}</h2>
    <p>{{ user.email }}</p>
  </div>
</template>

Composables

组合式函数

typescript
// composables/useApi.ts
import { ref } from 'vue';

export function useApi<T>(url: string) {
  const data = ref<T | null>(null);
  const error = ref<Error | null>(null);
  const isLoading = ref(false);

  async function execute() {
    isLoading.value = true;
    error.value = null;

    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Request failed');
      data.value = await response.json();
    } catch (e) {
      error.value = e as Error;
    } finally {
      isLoading.value = false;
    }
  }

  return { data, error, isLoading, execute };
}
typescript
// composables/useApi.ts
import { ref } from 'vue';

export function useApi<T>(url: string) {
  const data = ref<T | null>(null);
  const error = ref<Error | null>(null);
  const isLoading = ref(false);

  async function execute() {
    isLoading.value = true;
    error.value = null;

    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Request failed');
      data.value = await response.json();
    } catch (e) {
      error.value = e as Error;
    } finally {
      isLoading.value = false;
    }
  }

  return { data, error, isLoading, execute };
}

Pinia Store

Pinia 状态管理

typescript
// stores/user.ts
import { defineStore } from 'pinia';

interface UserState {
  user: User | null;
  isAuthenticated: boolean;
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    user: null,
    isAuthenticated: false,
  }),

  getters: {
    displayName: (state) => state.user?.name ?? 'Guest',
  },

  actions: {
    async login(credentials: LoginCredentials) {
      const user = await authService.login(credentials);
      this.user = user;
      this.isAuthenticated = true;
    },

    logout() {
      this.user = null;
      this.isAuthenticated = false;
    },
  },
});
typescript
// stores/user.ts
import { defineStore } from 'pinia';

interface UserState {
  user: User | null;
  isAuthenticated: boolean;
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    user: null,
    isAuthenticated: false,
  }),

  getters: {
    displayName: (state) => state.user?.name ?? 'Guest',
  },

  actions: {
    async login(credentials: LoginCredentials) {
      const user = await authService.login(credentials);
      this.user = user;
      this.isAuthenticated = true;
    },

    logout() {
      this.user = null;
      this.isAuthenticated = false;
    },
  },
});

TypeScript with Zod

TypeScript 结合 Zod 使用

Schema Definition

Schema 定义

typescript
import { z } from 'zod';

const UserSchema = z.object({
  id: z.number(),
  name: z.string().min(1),
  email: z.string().email(),
  role: z.enum(['user', 'admin']),
  createdAt: z.date(),
});

type User = z.infer<typeof UserSchema>;

const CreateUserSchema = UserSchema.omit({ id: true, createdAt: true });
type CreateUserInput = z.infer<typeof CreateUserSchema>;
typescript
import { z } from 'zod';

const UserSchema = z.object({
  id: z.number(),
  name: z.string().min(1),
  email: z.string().email(),
  role: z.enum(['user', 'admin']),
  createdAt: z.date(),
});

type User = z.infer<typeof UserSchema>;

const CreateUserSchema = UserSchema.omit({ id: true, createdAt: true });
type CreateUserInput = z.infer<typeof CreateUserSchema>;

Validation

数据验证

typescript
function createUser(input: unknown): User {
  const validatedInput = CreateUserSchema.parse(input);
  // Input is now typed as CreateUserInput
  return {
    ...validatedInput,
    id: generateId(),
    createdAt: new Date(),
  };
}

// Safe parsing (doesn't throw)
function validateUser(input: unknown) {
  const result = UserSchema.safeParse(input);
  if (!result.success) {
    console.error(result.error.issues);
    return null;
  }
  return result.data;
}
typescript
function createUser(input: unknown): User {
  const validatedInput = CreateUserSchema.parse(input);
  // Input is now typed as CreateUserInput
  return {
    ...validatedInput,
    id: generateId(),
    createdAt: new Date(),
  };
}

// Safe parsing (doesn't throw)
function validateUser(input: unknown) {
  const result = UserSchema.safeParse(input);
  if (!result.success) {
    console.error(result.error.issues);
    return null;
  }
  return result.data;
}

API Validation Middleware

API 验证中间件

typescript
import { z } from 'zod';
import { Request, Response, NextFunction } from 'express';

function validate<T extends z.ZodSchema>(schema: T) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body);
    if (!result.success) {
      return res.status(400).json({ errors: result.error.issues });
    }
    req.body = result.data;
    next();
  };
}

// Usage
app.post('/users', validate(CreateUserSchema), createUserHandler);
typescript
import { z } from 'zod';
import { Request, Response, NextFunction } from 'express';

function validate<T extends z.ZodSchema>(schema: T) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body);
    if (!result.success) {
      return res.status(400).json({ errors: result.error.issues });
    }
    req.body = result.data;
    next();
  };
}

// Usage
app.post('/users', validate(CreateUserSchema), createUserHandler);

General Best Practices

通用最佳实践

Error Handling

错误处理

  • Use custom error classes
  • Implement global error handlers
  • Log errors with context
  • Return appropriate status codes
  • 使用自定义错误类
  • 实现全局错误处理器
  • 附带上下文信息记录错误
  • 返回合适的状态码

Async Patterns

异步模式

  • Use async/await consistently
  • Handle promise rejections
  • Implement proper timeouts
  • Use Promise.all for parallel operations
  • 统一使用 async/await
  • 处理 Promise 拒绝
  • 实现合理的超时机制
  • 使用 Promise.all 进行并行操作

Testing

测试

  • Write unit tests for utilities
  • Integration tests for APIs
  • Use test fixtures
  • Mock external dependencies
  • 为工具函数编写单元测试
  • 为 API 编写集成测试
  • 使用测试夹具
  • 模拟外部依赖