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

如何将Dart服务端编译为JS并在Node.js/Firebase云函数运行?

在Firebase云函数中运行Dart服务端的解决方案

问题原因

你提到的编译为JS后无法使用dart:io是属实的。Dart的dart2js编译器主要针对浏览器环境,dart:io是仅面向Dart VM的服务端原生API,编译到JS后这些API会被禁用或无法正常工作——这就是为什么io.serve调用没有执行(连"Hello worl 2"都没输出),Node.js环境无法识别dart:io的服务器实现逻辑。

替代方案

1. 用Node.js原生API适配Shelf路由

通过node_interop库让Dart调用Node.js的HTTP API,将Shelf的请求处理逻辑适配到Node.js环境:

首先添加依赖到pubspec.yaml:

dependencies:
  shelf: ^1.4.0
  shelf_router: ^1.1.0
  node_interop: ^2.1.0
  node_http: ^1.0.0

修改代码如下:

import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:node_interop/http.dart';
import 'package:node_interop/util.dart';

void main() {
  print("Hello world once");
  var app = Router();

  app.get('/hello', (Request request) {
    return Response.ok('hello-world');
  });

  app.get('/user/<user>', (Request request, String user) {
    return Response.ok('hello $user');
  });

  // 将Shelf Handler适配为Node.js请求处理函数
  void handleRequest(HttpRequest nodeReq, HttpResponse nodeRes) async {
    // 转换Node.js请求为Shelf Request
    final shelfReq = Request(
      nodeReq.method,
      Uri.parse(nodeReq.url),
      headers: nodeReq.headers,
      body: await readStreamAsBytes(nodeReq),
    );

    // 用Shelf路由处理请求
    final shelfRes = await app(shelfReq);

    // 转换Shelf响应为Node.js响应
    nodeRes.statusCode = shelfRes.statusCode;
    shelfRes.headers.forEach((key, values) {
      nodeRes.setHeader(key, values.join(','));
    });
    nodeRes.end(await shelfRes.readAsString());
  }

  // 创建并启动Node.js HTTP服务器
  final server = http.createServer(allowInterop(handleRequest));
  server.listen(8080, 'localhost', () {
    print("Hello worl 2");
  });
}

编译运行:

dart compile js main.dart -o out.js
node out.js

此时服务器可正常启动并响应请求。

2. 直接使用Firebase云函数的Dart适配库

使用社区维护的firebase_functions_interop,直接对接Firebase云函数的触发机制,无需手动搭建HTTP服务器:

添加依赖:

dependencies:
  shelf: ^1.4.0
  shelf_router: ^1.1.0
  firebase_functions_interop: ^0.9.0

示例代码(HTTP触发的云函数):

import 'package:firebase_functions_interop/firebase_functions_interop.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';

void main() {
  var app = Router();

  app.get('/hello', (Request request) {
    return Response.ok('hello-world');
  });

  app.get('/user/<user>', (Request request, String user) {
    return Response.ok('hello $user');
  });

  // 将Shelf路由导出为Firebase HTTP函数
  functions['api'] = functions.https.onRequest(allowInterop((nodeReq, nodeRes) async {
    final shelfReq = Request(
      nodeReq.method,
      Uri.parse(nodeReq.path),
      headers: nodeReq.headers,
      body: await nodeReq.raw.body,
    );

    final shelfRes = await app(shelfReq);

    nodeRes.status(shelfRes.statusCode);
    shelfRes.headers.forEach((key, values) {
      nodeRes.set(key, values.join(','));
    });
    nodeRes.send(await shelfRes.readAsString());
  }));
}

编译为JS后,按照Firebase CLI的流程部署即可,无需手动管理服务器。

3. 注意事项

  • 确保所有依赖包支持JS编译,可在pub.dev查看包的「Platforms」标签,确认包含「JavaScript」;
  • 若使用Dart空安全,编译时可添加参数:dart compile js --enable-experiment=non-nullable main.dart -o out.js。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:05:35