如何在 PC 上本地测试 Cloud Functions for Firebase

Posted

技术标签:

【中文标题】如何在 PC 上本地测试 Cloud Functions for Firebase【英文标题】:how to test Cloud Functions for Firebase locally on pc 【发布时间】:2017-08-01 06:23:09 【问题描述】:

今天 Firebase 发布了它的全新产品 Cloud Functions for Firebase,我刚刚创建了一个 hello world 函数并将其部署到我现有的 firebase 项目中。

它看起来就像 aws lambda function 一样捆绑了所有依赖项并将其上传到 firebase。但是即使代码的微小变化也需要花费太多时间,并且还需要良好的互联网连接。如果您由于某种原因处于离线状态,那么在您有办法在本地计算机上离线执行和测试该功能之前,您只是不知道您正在编写什么代码。

有什么方法可以在本地测试 Cloud Functions for Firebase?

【问题讨论】:

【参考方案1】:

firebaser 在这里

部署您的函数确实比我通常愿意等待的时间要长。我们正在努力改进这一点,并且(正如 Brendan 所说)正在开发本地模拟器。

但目前,我主要是先将我的实际业务逻辑写入一个单独的 Node 脚本。这样我就可以在本地命令提示符下使用node speech.js 对其进行测试。一旦我对函数的工作感到满意,我要么将其复制/粘贴到我的实际函数文件中,要么(更好)将speech 模块导入我的函数文件并从那里调用它。

我很快找到的一个简短示例是我使用 Cloud Vision API 连接文本提取时。我有一个名为 ocr.js 的文件,其中包含:

var fetch = require('node-fetch');

function extract_text(url, gcloud_authorization) 
  console.log('extract_text from image '+url+' with authorization '+gcloud_authorization);

  return fetch(url).then(function(res) 
    return res.buffer();
  ).then(function(buffer) 
    return fetch('https://vision.googleapis.com/v1/images:annotate?key='+gcloud_authorization, 
      method: "POST",
      headers: 
        "Content-Type": "application/json"
      ,
      body: JSON.stringify(
        "requests":[
          
            "image":
              "content": buffer.toString('base64')
            ,
            "features":[
              
                "type":"TEXT_DETECTION",
                "maxResults":1
              
            ]
          
        ]
      )
    );
  ).then(function(res) 
    var json = res.json();
    if (res.status >= 200 && res.status < 300) 
      return json;
     else 
      return json.then(Promise.reject.bind(Promise));
    
  ).then(function(json) 
    if (json.responses && json.responses.length && json.responses[0].error) 
      return Promise.reject(json.responses[0].error);
    
    return json.responses[0].textAnnotations[0].description;
  );


if (process.argv.length > 2) 
  // by passing the image URL and gcloud access token, you can test this module
  process.argv.forEach(a => console.log(a));
  extract_text(
    process.argv[2], // image URL
    process.argv[3]  // gcloud access token or API key
  ).then(function(description) 
    console.log(description);
  ).catch(function(error) 
    console.error(error);
  );


exports.extract_text = extract_text;

然后在我的 Functions index.js 中,我有:

var functions = require('firebase-functions');
var fetch = require('node-fetch');
var ocr = require('./ocr.js');

exports.ocr = functions.database().path('/messages/room/id').onWrite(function(event) 
  console.log('OCR triggered for /messages/'+event.params.room+'/'+event.params.id);

  if (!event.data || !event.data.exists()) return;
  if (event.data.ocr) return;
  if (event.data.val().text.indexOf("https://firebasestorage.googleapis.com/") !== 0) return; // only OCR images

  console.log(JSON.stringify(functions.env));

  return ocr.extract_text(event.data.val().text, functions.env.googlecloud.apikey).then(function(text) 
    return event.data.adminRef.update( ocr: text );
  );
);

如您所见,最后一个文件实际上只是将“工作方法”ocr.extract_text 连接到数据库位置。

请注意,这是不久前的一个项目,因此某些语法(主要是 functions.env 部分)可能有所改变。

【讨论】:

您能否分享任何实际示例,或至少参考包含您在回答中描述的 hello world program 的任何存储库 测试在实践中是如何工作的?你提到你在命令行运行node speech.js。但这不测试你程序的操作逻辑是否正确?它只测试我猜的“设置”(即语法、依赖项等)?如果正确,有没有办法在本地测试操作逻辑? 我从命令行传入 GCP 需要的值。所以它测试我的脚本及其与外部 API 的交互。如果数据进入 Cloud Functions,它不会测试实际流量。【参考方案2】:

firebaser 在这里

要在本地调试 Cloud Functions for Firebase,有一个模拟器。请参阅documentation for more info。

【讨论】:

Alpha 版 Firebase 模拟器可用于 https 功能:firebase.google.com/docs/functions/local-emulator @BrianLenoski 似乎调试选项不见了?您提供的链接显示了如何在本地运行,而不是如何调试。【参考方案3】:

在本地运行和调试/检查函数

先决条件(google-cloud 功能和特定于 firebase):

npm install -g @google-cloud/functions-emulator
npm install --save firebase-functions
npm install -g firebase-tools

运行和检查/调试:首先在本地运行函数,然后检查每个函数,最后运行每个特定函数以调试+检查它。使用functions start 替代firebase serve,并注意每个工具的文档都可用(且有用)。

按预期运行和调试特定功能myFn(例如in Nodejs 通过chrome://inspect 并注意这可以使用Nodejs v10,但不受官方支持):

firebase serve --only functions
functions inspect myFn
functions call myFn # or call from browser

其他文档:

https://firebase.google.com/docs/functions/local-emulator https://cloud.google.com/functions/docs/emulator#debug-emulator https://github.com/GoogleCloudPlatform/cloud-functions-emulator/wiki

【讨论】:

可以做单步吗?允许检查变量的值吗? 我收到Error: FIREBASE FATAL ERROR: Cannot parse Firebase url. Please use https://&lt;YOUR FIREBASE&gt;.firebaseio.com【参考方案4】:

>> 有什么方法可以在本地测试 Cloud Functions for Firebase?

您可以使用以下命令启动 firebase shell(在您的函数目录中执行):

npm run build && firebase functions:shell

你可以像这样在 shell 中调用你的函数:

helloWorld()

请参阅this 链接了解更多信息。

【讨论】:

【参考方案5】:

在这里回答:https://github.com/firebase/firebase-functions/issues/4#issuecomment-286515989

Google Cloud Functions 还开源了一个本地模拟器,我们正在 致力于与 Cloud Functions 建立更紧密的集成 火力基地。同时,您可以在这里查看: https://github.com/GoogleCloudPlatform/cloud-functions-emulator/

模拟器允许您在本地运行函数。这是 解释如何使用它的文档: https://cloud.google.com/functions/docs/emulator

【讨论】:

【参考方案6】:

一开始我无法让单步执行。我的过程与此处许多答案中记录的过程相同。

此外,这些页面几乎包含我需要的所有文档:

https://firebase.google.com/docs/functions/local-emulator https://cloud.google.com/functions/docs/emulator#debugging_with_the_emulator

我已经使用firebase serve --only functions 运行了函数,但还没有启动并运行调试器。然后我遇到了直接使用模拟器的另一种方式,并设法达到了这样的断点:

# start the emulator
functions start

# allow inspection
functions inspect helloWorld

# call the function from the cli
functions call helloWorld

这行得通,我可以打断点。

但是,当在邮递员或浏览器中点击函数的端点时,我根本没有得到任何响应。

我缺少的步骤是:

# deploy the function to the emulator
functions deploy helloWorld --trigger-http

# you need to toggle inspection after the deploy
functions inspect helloWorld

现在我可以从邮递员或浏览器中命中函数的端点,并命中断点。

我推荐出色的 NiM chrome extension 进行调试,并希望这个答案对某人有所帮助,即使这是一个老问题。

【讨论】:

【参考方案7】:

首先,我建议你安装以下依赖项,

npm install --save firebase-functions
npm install -g firebase-tools 

如果已经安装,那么您可以将其更新到最新版本。一般来说,functions-emulator 都有上述依赖,但我还是建议你更新它,

npm install -g @google-cloud/functions-emulator

更新后,进入应用程序的functions文件夹并运行以下命令,

firebase serve --only functions

希望对你有帮助!

【讨论】:

【参考方案8】:

适用于调试 HTTP 函数(webhooks 等)的 vscode 用户...

谷歌云模拟器 (firebase serve --only functions) 会启动一个单独的进程来运行您的函数。您可以使用 vscode 附加到此进程,但由于模拟器仅在调用第一个函数之后创建此进程,因此并不简单。

在您的函数中创建一个虚拟 HTTP 端点,该端点将返回 processID:
app.get("/processid", function(request, response) 
  response.send(`$process.pid`);
);
firebase serve --only functions启动模拟器 调用http://&lt;localhost_url&gt;/processid 端点。这将创建进程并返回 processID 使用 vscode 附加到指定进程。您现在可以在任何其他函数上设置断点、步骤等(它们都使用相同的过程)。

可能有更好的方法将所有这些粘合在一起。

【讨论】:

我发现在 index.js 的顶部记录 process.pid 更容易。它会针对每个新进程进行评估,并且会在您运行“firebase serve”后立即发生 - 无需发出请求即可获得它。 @Tom 除了这似乎不起作用。正如我所提到的,当调用第一个函数时会启动一个新进程。您可以通过查看 index.js 顶部记录的进程 ID 与 /processid 函数调用返回的进程 ID 不同来验证这一点。 哦,这很奇怪。我很确定它对我有用。我会在下次处理该问题时重新检查 - 也许它的行为在这方面不一致。 感谢@adelphus,这正是我一直在寻找的东西,很好。 如何附加到进程?【参考方案9】:

现在有一个云functions emulator that 可以让你在本地调用函数

完成 PoC 后,我将更新此答案以包含我使用的代码和步骤。

【讨论】:

以上是关于如何在 PC 上本地测试 Cloud Functions for Firebase的主要内容,如果未能解决你的问题,请参考以下文章