3

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

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

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

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

4

1 回答 1

2

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

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

const router = express.Router();

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

export default router;

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

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);
  }
}

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

// $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;

然后在您的主功能文件中,您将按需连接您的子功能文件:

// $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()多次。

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

admin.initializeApp();

export = admin;

在任何想要使用的函数中"firebase-admin",您可以使用以下命令从此处导入它:

// $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
于 2021-03-26T10:27:36.240 回答