You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js函数式组件中调用.NET 6 gRPC服务端?

解决Next.js(TypeScript)调用.NET 6 gRPC服务的方案

一、错误原因说明

你使用的grpc和@grpc/proto-loader是Node.js专属库,依赖Node.js的fs文件系统模块,但浏览器环境没有该模块,因此在Next.js客户端组件中运行会出现Can't resolve 'fs'的错误。浏览器无法直接调用原生gRPC服务,必须通过gRPC-Web协议做适配。

二、前置准备:配置.NET 6 gRPC服务支持gRPC-Web

首先需要让你的.NET gRPC服务兼容gRPC-Web协议:

  1. 在gRPC服务项目中安装NuGet包:Grpc.AspNetCore.Web
  2. 修改Program.cs添加gRPC-Web支持:
var builder = WebApplication.CreateBuilder(args);

// 注册gRPC服务
builder.Services.AddGrpc();

var app = builder.Build();

// 启用gRPC-Web中间件(需放在MapGrpcServices之前)
app.UseGrpcWeb();

// 映射Greeter服务并允许gRPC-Web访问
app.MapGrpcService<GreeterService>().EnableGrpcWeb();

app.Run();

三、Next.js项目配置步骤

1. 安装依赖包

安装gRPC-Web客户端相关工具:

npm install @grpc/grpc-web @improbable-eng/grpc-web google-protobuf
npm install -D protobuf-loader-typescript-plugin @types/google-protobuf

2. 编译.proto文件生成TypeScript代码

手动编写TS类型效率低,用工具将.proto文件编译成可直接使用的TS代码:

  • 将你的greet.proto文件放到Next.js项目的proto目录下(例如/proto/greet.proto)
  • 在项目根目录创建proto-gen.js脚本:
const path = require('path');
const protobuf = require('protobufjs');
const { generateTsCode } = require('@improbable-eng/grpc-web/codegen');

// 加载并编译proto文件
protobuf.load(path.resolve(__dirname, './proto/greet.proto'), (err, root) => {
  if (err) throw err;
  const outputPath = path.resolve(__dirname, './src/generated/greet.ts');
  // 生成TypeScript客户端代码
  const tsCode = generateTsCode(root, 'greet.proto', {
    outputPath,
  });
  // 写入文件
  require('fs').writeFileSync(outputPath, tsCode);
});
  • 在package.json中添加编译命令:
"scripts": {
  "proto:gen": "node proto-gen.js"
}
  • 运行命令生成代码:
npm run proto:gen

生成的代码会保存在src/generated/greet.ts,包含gRPC客户端和消息类型的完整定义。

3. 编写Next.js函数式组件实现点击调用

修改pages/index.tsx,使用生成的代码实现点击触发gRPC调用:

import type { NextPage } from "next";
import styles from "../styles/Home.module.css";
import { GreeterClient } from "../src/generated/greet";
import { HelloRequest } from "../src/generated/greet_pb";

const Home: NextPage = () => {
  // 初始化gRPC-Web客户端(替换为你的.NET服务地址)
  const client = new GreeterClient("http://localhost:5000", null, null);

  const grpcCall = () => {
    const request = new HelloRequest();
    request.setName("Say Hello");

    // 回调模式调用gRPC接口
    client.sayHello(request, {}, (err, response) => {
      if (err) {
        console.error("调用失败:", err);
        return;
      }
      console.log("gRPC响应:", response?.getMessage());
      alert(`收到响应: ${response?.getMessage()}`);
    });

    // 也可以使用Promise模式:
    // client.sayHelloPromise(request, {})
    //   .then(response => alert(`收到响应: ${response.getMessage()}`))
    //   .catch(err => console.error("调用失败:", err));
  };

  return (
    <div className={styles.container}>
      <div onClick={grpcCall} className={styles.title} style={{cursor: 'pointer'}}>
        Press to call gRPC HERE
      </div>
    </div>
  );
};

export default Home;

四、关键注意事项

  • 端口与协议:gRPC-Web默认使用HTTP/HTTPS,确保.NET服务的HTTP端口(例如5000)正常开启,客户端地址需与服务地址完全匹配。
  • 跨域处理:若Next.js与gRPC服务不在同一域名/端口,需在.NET服务中配置CORS:
    在Program.cs中添加:
    builder.Services.AddCors(options =>
    {
        options.AddPolicy("AllowAll", policy =>
        {
            policy.AllowAnyOrigin()
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
        });
    });
    
    // 在UseGrpcWeb之前启用CORS
    app.UseCors("AllowAll");
    
  • 调用模式:gRPC-Web支持回调和Promise两种调用模式,可根据需求选择。

内容的提问来源于stack exchange,提问作者Raitis Lebedevs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:39:25