无法在模块外使用导入语句,TypeScript NodeJS Firebase Functions 项目。

5

我最近使用TypeScript建立了一个Firebase Functions项目。据我所知,我使用的是过去相同的设置。然而,这次当我运行firebase emulators:start时,我收到了以下错误:

Error: Error occurred while parsing your function triggers.

<Local Computer Path>/firebase/functions/src/index.ts:3
import functions = require("firebase-functions");
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at loadModule (/opt/homebrew/lib/node_modules/firebase-tools/lib/deploy/functions/runtimes/node/triggerParser.js:10:16)
    at /opt/homebrew/lib/node_modules/firebase-tools/lib/deploy/functions/runtimes/node/triggerParser.js:34:21

据我所知,我没有改变过以往的项目,在那些项目中我没有遇到过这个问题。我唯一能想到的潜在差异是我使用了npm install -g firebase-tools@latest 更新了我的firebase工具。以下是我项目中的一些文件:

src/index.ts

/* eslint-disable max-len */
import functions = require("firebase-functions");
import admin = require("firebase-admin");

admin.initializeApp();

...

.eslintrc.js

module.exports = {
  root: true,
  env: {
    es6: true,
    node: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "google",
    "plugin:@typescript-eslint/recommended",
  ],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: ["tsconfig.json", "tsconfig.dev.json"],
    sourceType: "module",
    tsconfigRootDir: __dirname,
  },
  ignorePatterns: [
    "/lib/**/*", // Ignore built files.
  ],
  plugins: [
    "@typescript-eslint",
    "import",
  ],
  rules: {
    "indent": ["error", 2],
    "object-curly-spacing": ["error", "always"],
    "quotes": ["error", "double"],
    "import/no-unresolved": 0,
  },
};

package.json

{
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "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"
  },
  "engines": {
    "node": "16"
  },
  "main": "./src/index.ts",
  "dependencies": {
    "firebase-admin": "^10.0.2",
    "firebase-functions": "^3.18.0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.25.4",
    "firebase-functions-test": "^0.2.0",
    "typescript": "^4.5.4"
  },
  "private": true,
  "type": "module",
  "module": "ES2020"
}

package.dev.json

{
  "include": [
    ".eslintrc.js"
  ]
}

tsconfig.json

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

firebase.json

{
  ...
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  },
  ...
}

我的src/index.ts导入语法与Google在Firestore文档中所述的相匹配:导入必需的模块并初始化应用程序
我已经搜索了答案,但尚未找到。以下是我尝试过的一些资源: SyntaxError: 在Firebase Functions中不能在模块外使用导入语句 Node.js v13.14.0 文档 Typescript:无法在模块外使用导入语句 提前感谢您的帮助!
2个回答

8
结果证明这个问题有一个简单的解决方案!Firebase模拟器不支持TypeScript。要在模拟器中运行函数,您首先需要将其编译为JS(请参考文档)。npm run servefirebase deploy都会自动转换您的代码,firebase emulators:start不会自动执行此操作。在使用模拟器时,您必须先在函数文件夹中运行npm run build
另外请注意,在您的package.json中,您需要将main参数引用编译后的JS代码。我需要更新我的package.jsontsconfig.json。以下是最终版本: package.json
{
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "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"
  },
  "engines": {
    "node": "16"
  },
  "main": "./lib/index.js",
  "dependencies": {
    "firebase-admin": "^10.0.2",
    "firebase-functions": "^3.18.0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.25.4",
    "firebase-functions-test": "^0.2.0",
    "typescript": "^4.5.4"
  },
  "private": true
}

tsconfig.json

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

1

您需要使用const functions = require("firebase-functions");而不是import functions = require("firebase-functions"); - 对于下面的第二个导入也是一样的。'import'关键字只能用于esmodules,而const/require语法用于commonjs。


Ross,感谢您的回复。这解决了我从node_modules导入的问题。但是,当我尝试从另一个文件中导入函数时,该语法不起作用:const account = require("./account")。这就是我想要实现的内容:分组函数 - Bernard
非常感谢。您的建议对我很有帮助。我遇到了这个问题一段时间。一旦我从函数文件夹中使用npm run build构建代码以生成JS,它就解决了这个问题。Firebase仿真器成功启动。在此之前,我一直收到以下错误,但现在不再面临同样的问题import * as admin from 'firebase-admin' SyntaxError: Cannot use import statement outside a module我没有必要在package.json中使用"type": "module"。我能够像import * as admin from 'firebase-admin'这样使用导入。 - Arif Shaikh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接