【前端分享】Node.js 后端与前端全栈开发趋势!

Node.js 后端与前端全栈开发趋势

1. 问题概述

全栈开发正在成为前端开发者的主流方向。Next.js、Nuxt、Remix、Astro 等框架模糊了前后端边界,Node.js 运行时也在快速发展(Bun、Deno 等)。了解全栈开发的最新趋势对前端开发者至关重要。

2. 全栈框架格局

2.1 Next.js(React)

复制代码
// 同一项目中编写前后端代码
// app/api/posts/route.ts
exportasyncfunctionGET() {
const posts = await db.post.findMany()
returnResponse.json(posts)
}

// app/posts/page.tsx
asyncfunctionPostsPage() {
const posts = awaitfetch('/api/posts').then(r => r.json())
return posts.map(p =><PostCard key={p.id} post={p} />)
}

2.2 Nuxt 4(Vue)

复制代码
<!-- server/api/posts.ts -->
export default defineEventHandler(async () => {
  return await db.post.findMany()
})

2.3 Remix(React Router 生态)

复制代码
export async function loader() {
  return json(await db.post.findMany())
}

export default function Posts() {
  const posts = useLoaderData<typeof loader>()
}

2.4 Astro(内容型网站)

复制代码
---
// 服务端代码
const posts = await Astro.db.find('posts')
---
<ul>
  {posts.map(post => <li>{post.title}</li>)}
</ul>

2.5 SvelteKit(Svelte)

复制代码
// +page.server.ts
export async function load() {
  return { posts: await db.post.findMany() }
}

3. 运行时选择

运行时 特点 包管理 适用场景
Node.js 最成熟稳定 npm/pnpm/yarn 通用
Bun 极快、All-in-one bun 开发/简单服务
Deno 安全优先、TS 原生 deno 安全敏感项目
WinterJS Wasm 兼容 - 边缘计算

4. 数据库与 ORM

4.1 Prisma

复制代码
// schema.prisma
model Post {
  id      Int     @id @default(autoincrement())
  title   String
  content String?
}

4.2 Drizzle ORM

复制代码
// 零运行时、类型安全、SQL-like
const posts = await db
  .select()
  .from(postsTable)
  .where(eq(postsTable.status, 'published'))

4.3 对比

ORM 特点 性能 学习曲线
Prisma DX 极佳、迁移工具好
Drizzle 零运行时、接近 SQL
Kysely 类型安全 SQL 构建器 中高

5. 部署平台

平台 特点 免费额度
Vercel Next.js 原生、边缘函数 慷慨
Cloudflare Workers 边缘计算、全球分布 慷慨
Railway 简单部署、数据库内置 有限
Fly.io 全球边缘部署 有限
自建 VPS 完全控制 按需

6. 全栈开发趋势

  1. Server Actions 普及:表单处理直接在组件中,无需 API 路由

  2. 边缘计算增长:边缘数据库(如 Turso、Neon、PlanetScale)让数据更贴近用户

  3. RSC 改变架构:服务端组件成为主流,减少客户端 JS

  4. TypeScript 端到端:前后端类型共享,tRPC/Zod 实现全链路类型安全

  5. Bun 生态成熟:替代 Node.js 的潜力,内置打包、测试、包管理

  6. Rust 工具链渗透:SWC、Rspack、Oxc 等 Rust 工具提升构建性能

7. 端到端类型安全实战

7.1 tRPC 模式

复制代码
// server/trpc.ts
import { initTRPC } from'@trpc/server';
import { z } from'zod';

const t = initTRPC.create();

exportconst appRouter = t.router({
posts: {
    list: t.procedure.query(() => db.post.findMany()),
    byId: t.procedure.input(z.string()).query(({ input }) =>
      db.post.findUnique({ where: { id: input } })
    ),
    create: t.procedure
      .input(z.object({ title: z.string().min(3), content: z.string() }))
      .mutation(({ input }) => db.post.create({ data: input })),
  },
});

exporttypeAppRouter = typeof appRouter;

// app/posts/page.tsx - 前端使用
'use client';
import { trpc } from'@/lib/trpc';

functionPostList() {
const { data, isLoading } = trpc.posts.list.useQuery();
const createPost = trpc.posts.create.useMutation({
    onSuccess: () => {
      // 自动刷新列表
    },
  });

if (isLoading) return<div>Loading...</div>;

return (
    <div>
      {data?.map(post => <PostCard key={post.id} post={post} />)}
    </div>
  );
}

7.2 共享类型定义

复制代码
// shared/types.ts - 前后端共享
exportinterfacePost {
id: string;
title: string;
content: string;
createdAt: Date;
author: User;
}

// 后端直接使用
importtype { Post } from'@/shared/types';
asyncfunctiongetPost(id: string): Promise<Post> { ... }

// 前端也使用同一类型
importtype { Post } from'@/shared/types';
const [post, setPost] = useState<Post | null>(null);

8. 认证与授权方案

8.1 NextAuth.js / Auth.js

复制代码
// app/api/auth/[...nextauth]/route.ts
importNextAuthfrom'next-auth';
importGitHubfrom'next-auth/providers/github';
importGooglefrom'next-auth/providers/google';

exportconst { handlers, auth, signIn, signOut } = NextAuth({
providers: [GitHub, Google],
callbacks: {
    asyncsession({ session, token }) {
      // 扩展 session 信息
      session.user.id = token.sub!;
      return session;
    },
  },
});

// Server Component 中获取会话
import { auth } from'@/auth';

exportdefaultasyncfunctionDashboard() {
const session = awaitauth();
if (!session) return<div>请先登录</div>;

return<div>欢迎, {session.user?.name}</div>;
}

8.2 中间件保护

复制代码
// middleware.ts
export { auth as middleware } from '@/auth';

export const config = {
  matcher: ['/dashboard/:path*', '/api/protected/:path*'],
};

9. 数据库与 ORM 深入

9.1 Drizzle ORM 实战

复制代码
// db/schema.ts
import { pgTable, serial, text, timestamp, integer } from'drizzle-orm/pg-core';

exportconst posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});

exportconst users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').unique().notNull(),
});

// db/queries.ts
import { db } from'./index';
import { posts, users } from'./schema';
import { eq, desc, and } from'drizzle-orm';

exportasyncfunctiongetRecentPosts(limit = 10) {
return db
    .select({
      id: posts.id,
      title: posts.title,
      authorName: users.name,
      createdAt: posts.createdAt,
    })
    .from(posts)
    .leftJoin(users, eq(posts.authorId, users.id))
    .orderBy(desc(posts.createdAt))
    .limit(limit);
}

10. 部署与运维

10.1 Docker 化

复制代码
# Dockerfile
FROM node:20-alpine AS base
WORKDIR /app

FROM base AS deps
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

FROM base AS builder
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN pnpm build

FROM base AS runner
ENV NODE_ENV production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE3000
CMD ["node", "server.js"]

10.2 环境变量管理

复制代码
# .env.local(不提交到 Git)
DATABASE_URL="postgresql://localhost:5432/mydb"
AUTH_SECRET="your-secret-key"

# .env.example(提交到 Git,作为模板)
DATABASE_URL="postgresql://localhost:5432/mydb"
AUTH_SECRET="generate-a-random-secret"

11. 参考资源

  • Next.js 文档:

  • Astro 文档

  • Bun 官方

  • Drizzle ORM 文档