mkdir ai-assistant
cd ai-assistant
mkdir apps
# git
git init
ni .gitignore
# pnpm
pnpm init
ni pnpm-workspace.yaml
pnpm-workspace.yaml 配置
packages:
# all apps in direct subdirs of apps/
- 'apps/*'
cd apps
nest new server --strict --skip-git --package-manager=pnpm
# --strict 严格模式
# --skip-git 不初始化 git
# --package-manager=pnpm 使用 pnpm
# 检查 server 是否正常运行
cd server
pnpm run start:dev
注意 nestjs 的默认端口与 nextjs 冲突都是 3000 可以修改为 4000
回到 apps/
目录
pnpx create-next-app@latest
What is your project named? # web (change to whatever you want)
Would you like to use TypeScript with this project? # Yes
Would you like to use ESLint with this project? # Yes
Would you like to use Tailwind CSS with this project? Yes # Yes
Would you like to use `src/` directory with this project? # No
Use App Router (recommended)? # Yes
Would you like to customize the default import alias? # No
cd /web
pnpm dev
tRPC server 运行在 nestjs 端,tRPC client 运行在 nextjs 端
tRPC 客户端将需要访问一个名为 Axpoutouter 的类型,该类型在 nestjs 应用程序内定义。
当前这是无法实现的,因为只能从应用所在的程序中导入类型声明
我们需要通过 typescript 配置来解决这个问题
转到项目根目录添加 tsconfig.json
文件
pnpm install --save-dev -w typescript
npx tsc --init
{
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": true,
"noImplicitAny": true,
"strictBindCallApply": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"paths": {
"@server/*": ["./apps/server/src/*"],
"@web/*": ["./apps/web/*"]
}
}
}
更新 nestjs 的 tsconfig
{
"extends": "../../tsconfig.json",
"compilerOptions": {
// "emitDecoratorMetadata": true,
// "experimentalDecorators": true,
// "target": "ES2021",
// "baseUrl": "./",
// "incremental": true,
// "skipLibCheck": true,
// "strictNullChecks": true,
// "noImplicitAny": true,
// "strictBindCallApply": true,
// "forceConsistentCasingInFileNames": true,
// "noFallthroughCasesInSwitch": true,
"module": "commonjs",
"declaration": true,
"removeComments": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"outDir": "./dist",
}
}
更新 nextjs 的 tsconfig
{
"extends": "../../tsconfig.json",
"compilerOptions": {
// "skipLibCheck": true,
// "paths": {
// "@/*": [
// "./*"
// ]
// },
"target": "ES5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
在根目录的 package.json
中添加 scripts
{
"scripts": {
"dev": "pnpm run --parallel dev",
},
}
更新 server 的 package.json
中的 scripts
,以实现 dev
命令
{
"scripts": {
"dev": "pnpm run start:dev",
},
}
最后需要注意,在根目录使用 pnpm add @nestjs/config --filter=server
安装依赖时会遇到 miss peer dependency error
apps/server
└─┬ ts-loader 9.4.3
└── ✕ missing peer webpack@^5.0.0
Peer dependencies that should be installed:
webpack@^5.0.0
这是由于在 monorepo 中,软件包管理器不会自动处理工作空间中各个应用程序的 peer dependencies
,因此需要在 nestjs 中手动安装
安装依赖
pnpm add @trpc/server zod --filter=server
在 nestjs 中添加 tRPC 模块
mkdir apps/server/src/trpc
ni apps/server/src/trpc/trpc.module.ts
ni apps/server/src/trpc/trpc.service.ts
ni apps/server/src/trpc/trpc.router.ts
实现看具体代码
在 tRPC router 中定义接口会导致文件膨胀,可以通过 Merging Routers 来拆分路由
tRPC 服务准备好后需要在 main.ts
中添加中间件
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { TrpcRouter } from '@server/trpc/trpc.router';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
const trpc = app.get(TrpcRouter);
trpc.applyMiddleware(app);
await app.listen(4000);
}
bootstrap();
安装 tRPC 客户端包
在根目录运行
pnpm add @trpc/client @trpc/server --filter=web
创建 tRPC 客户端
ni apps/web/app/trpc.ts
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
import { AppRouter } from '@server/trpc/trpc.router'
export const trpc = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: "http://localhost:4000/trpc", // 您应该将其更新以使用 ENV 变量
}),
],
});