使用 expressjs 优化 firebase 功能冷启动 [英] Optimizing firebase functions cold start with expressjs

查看:19
本文介绍了使用 expressjs 优化 firebase 功能冷启动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚如何优化我的 firebase 功能的冷启动时间.阅读后 这篇文章,我想尝试一下,但我意识到这篇文章专门针对http onRequest函数的基本用法,并没有给出使用express的示例.

I was trying to figure out how I could optimize cold start times for my firebase functions. After reading this article, I wanted to try it out but I realized that the article specifically targets the base usage of the http onRequest function and doesn't give an example using express.

一个类似的问题弹出在这里 但似乎没有明确的答案.我看到文章的作者 Doug 实际上评论了这个问题,他提到要为应用程序中的每个路由创建动态导入,因为 onRequest() 只允许将应用程序作为其唯一参数传递,但是除了在没有 express 应用程序的情况下使用基本 API 之外,我并不完全理解他的意思.理想情况下,我可以使用 express,这样我就可以更好地控制 api url 路径并使用一些 express 提供的实用程序.

A similar question popped up here but doesn't seem like there's a clear answer. I saw the author of the article Doug actually commented on the question and he mentions to create a dynamic import for each route in the app since onRequest() only allows for passing the app as its only argument, but I wasn't understanding exactly what he meant by that other than to use the base API without the express app. Ideally I'd be able to use express so I can have finer control over the api url paths and use some of utility that express offers.

谁能给我举个例子,说明如何在 Doug 的例子中使用 express?即使我必须为每条路线定义一个新的快速应用程序,我也可以接受.只是不知道如何以这种方式配置它.

Can anyone give me an example of how to use express with Doug's example? Even if I have to define a new express app for each route, I'm okay with that. Just don't see how to configure it that way.

EDIT:明确地说,目标是优化冷启动所有函数调用,而不仅仅是 http 路由调用.根据我的理解,Doug 的示例消除了使用 onRequest 声明的单个路由预加载的导入,但它没有显示通过 express 定义路由时如何实现.

EDIT: To be clear, the goal is to optimize cold starts across all function invocations, not just the http routed ones. From my understanding, Doug's example eliminates the imports being preloaded with single routes declared using onRequest, but it doesn't show how that is possible when defining routes through express.

推荐答案

假设您拆分的每个路由器都在其自己的文件中定义,如下所示:

Assuming each router you split out is defined in it's own file like so:

// $FUNCTIONS_DIR/routes/some-route-handler.js
import express from "express";

const router = express.Router();

/* ... define routes ... */

export default router;

然后您可以使用此中间件仅在需要时加载每个路由处理程序模块.

You could then use this middleware to load each route handler module only when it's needed.

function lazyRouterModule(modulePath) {
  return async (req, res, next) {
    let router;

    try {
      router = (await import(modulePath)).default;
    } catch (err) {
      // error loading module, let next() handle it
      next(err);
      return;
    }
    
    router(req, res, next);
  }
}

在您的子功能文件中,您将使用该中间件来创建您的 express 应用程序并连接路由.

In your sub-function file, you'd use that middleware to create your express app and connect the routes.

// $FUNCTIONS_DIR/fn/my-express.js
import express from "express";

const app = express();

app.use('/api', lazyRouterModule('./routes/api.js'));

app.use('/profiles', lazyRouterModule('./routes/profiles.js'));

export default app;

然后在您的主函数文件中,您可以按需连接子函数文件:

Then in your main functions file, you'd connect up your subfunction files on-demand:

// $FUNCTIONS_DIR/index.js
import * as functions from 'firebase-functions'

export const myExpress = functions.https
  .onRequest(async (request, response) => {
    await (await import('./fn/my-express.js')).default(request, response)
  });

export const newUserData = functions.firestore.document('/users/{userId}')
  .onCreate(async (snap, context) => {
    await (await import('./fn/new-user-data.js')).default(snap, context)
  });

当像这样延迟加载模块时,您将希望从公共文件延迟加载 firebase-admin,这样您就不会最终调用 initializeApp()多次.

When lazy-loading modules like this, you will want to lazy-load firebase-admin from a common file so you don't end up calling initializeApp() multiple times.

// $FUNCTIONS_DIR/common/firebase-admin.js
import * as admin from "firebase-admin";

admin.initializeApp();

export = admin;

在任何想要使用 "firebase-admin" 的函数中,您可以从这里使用:

In any function that wants to use "firebase-admin", you'd import it from here using:

// $FUNCTIONS_DIR/fn/some-function.js OR $FUNCTIONS_DIR/routes/some-route-handler.js
import * as admin from "../common/firebase-admin";

// use admin as normal, it's already initialized

这篇关于使用 expressjs 优化 firebase 功能冷启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆