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

使用ES Module部署TypeScript编写的Firebase函数遇阻求助

部署ES Module格式的TypeScript Firebase函数时的模块查找问题

我在部署TypeScript编写、采用ES Module系统的Firebase函数时遇到了模块找不到的问题。相关代码文件如下:

index.ts

import * as functions from "firebase-functions";
import myGreeting from "./my-greeting";

export const helloWorld = functions.https.onRequest((request, response) => {
  response.send(myGreeting);
});

my-greeting.ts

export default "HELLO WORLD";

tsconfig.json

{
  "compilerOptions": {
    "module": "ES2020",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "moduleResolution": "node",
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "ES2020"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

package.json

{
  "name": "functions",
  "scripts": {
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "type": "module",
  "engines": {
    "node": "16"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^10.2.0",
    "firebase-functions": "^3.21.0"
  },
  "devDependencies": {
    "typescript": "^4.6.4"
  },
  "private": true
}

代码可以正常编译,但TypeScript编译器不会在输出的./lib/index.js导入语句中添加.js扩展名,部署时出现以下错误:

Error: Failed to load function definition from source: Failed to generate manifest from function source: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/my-project/functions/lib/my-greeting' imported from /my-project/functions-test/functions/lib/index.js

我需要导入一个仅提供ES Module版本(无CommonJS版本)的npm库,该库的导入语句也不含.js后缀。Node.js 16理论上支持ES2020规范的ES Module,但Firebase函数运行时无法设置--experimental-specifier-resolution=node标志。

我需要在不转为CommonJS模块的前提下,让函数在Node.js 16的Firebase云运行时成功部署并运行。以下两种方案不可行:

  1. 无法直接修改导入语句:手动给所有导入语句添加.js后缀过于繁琐,且依赖的第三方ES Module库本身就不含这类后缀,无法逐一修改。
  2. 无法切换为CommonJS模块:若将tsconfig.json的module改为CommonJS并移除package.json中的type: module,示例代码可正常部署,但我依赖的库仅提供ES Module版本,无法兼容CommonJS。

可行解决方案

方案1:使用tsc-alias自动补全.js后缀

tsc-alias可以在TypeScript编译完成后,自动将相对导入路径补全为带.js后缀的格式,符合Node.js ES模块的要求:

  1. 安装开发依赖:
    npm install --save-dev tsc-alias
    
  2. 修改package.json中的build脚本:
    "scripts": {
      "build": "tsc && tsc-alias",
      // 其他脚本保持不变
    }
    
  3. 正常执行npm run build后,编译生成的lib目录下的文件会自动补全导入语句的.js后缀,部署即可正常运行。

方案2:使用ESBuild替代TypeScript编译器

ESBuild是一个快速的JavaScript/TypeScript打包工具,默认会处理ES模块的导入后缀问题,同时支持直接输出符合Node.js要求的ES模块:

  1. 安装开发依赖:
    npm install --save-dev esbuild
    
  2. 修改package.json中的build脚本(如需保留类型检查,可新增类型检查脚本):
    "scripts": {
      "build": "esbuild src/index.ts --bundle --outfile=lib/index.js --platform=node --target=node16 --format=esm",
      "type-check": "tsc --noEmit",
      "serve": "npm run type-check && npm run build && firebase emulators:start --only functions",
      // 其他脚本按需调整
    }
    
  3. ESBuild会自动处理所有模块导入的后缀,同时可以将代码打包为单个文件,避免模块查找问题。

方案3:调整TypeScript配置为NodeNext模式

TypeScript的NodeNext模块模式会严格遵循Node.js的模块解析规则,编译ES模块时会自动添加.js后缀:

  1. 修改tsconfig.json的compilerOptions:
    {
      "compilerOptions": {
        "module": "NodeNext",
        "moduleResolution": "NodeNext",
        "target": "ES2020",
        // 保留其他原有配置(noImplicitReturns、noUnusedLocals等)
      },
      // 其他配置保持不变
    }
    
  2. 确保package.json中的type仍为module,然后正常执行npm run build即可。此方案需要TypeScript 4.7及以上版本支持。

注:Firebase Cloud Functions运行时不支持自定义Node.js启动参数,因此无法通过添加--experimental-specifier-resolution=node来绕过后缀检查,必须通过编译层面解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:05:23