使用typescript在Firebase Cloud函数内部动态导入类的正确方法是什么



在Firebase Cloud Function项目中

我在src目录的根目录下,就在主index.ts文件的旁边,有以下类型脚本文件,该文件导入一个依赖项并导出一个包含2个方法的类。此文件的标题为bcrypt.class.ts:

import * as bcrypt from 'bcryptjs';
export default class BcryptTool {
public static hashValue(value: string, rounds: number, callback: (error: Error, hash: string) => void) : void {
bcrypt.hash(value, rounds, (error:any, hash:any) => {
callback(error, hash);
});
}
public static compare(value: string, dbHash: string, callback: (error: string | null, match: boolean | null) => void) {
bcrypt.compare(value, dbHash, (err: Error, match: boolean) => {
if(match) {
callback(null, true);
} else {
callback('Invalid value match', null);
}
});
}
}

在我的Firebase Cloud函数index.ts文件中,我导入了这个类,并在我的一个函数中调用了它的"compare"方法,没有问题,这正如预期的那样工作:

'use strict';
const express = require('express');
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true });
const admin = require('firebase-admin');
admin.initializeApp();
const api = express();
import BcryptTool from './bcrypt.class'; // <-- i import the class here
// and use it in a function
api.use(cors);
api.post('/credentials', async (request: any, response: any) => {
BcryptTool.compare(...) // <--- calls to this method succeed without issue
});

问题

我的应用程序包括许多函数,但我只需要其中一个函数中的上述类,因此,为了优化所有其他函数的冷启动时间,我尝试在需要它的函数内部动态导入该类,而不是如上所述将其导入全局范围。这不起作用,我不知道为什么:

'use strict';
const express = require('express');
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true });
const admin = require('firebase-admin');
admin.initializeApp();
const api = express();
api.use(cors);
api.post('/credentials', async (request: any, response: any) => {
const BcryptTool = await import('./bcrypt.class'); // <-- when i attempt to import here instead
BcryptTool.compare(...) // <--- subsequent calls to this method fail
// Additionally, VS Code hinting displays a warning: Property 'compare' does not exist on type 'typeof import('FULL/PATH/TO/MY/bcrypt.class')' 
});

我的类是否未正确写入或导出?

我没有在云函数中正确导入类吗?

顶级导入(import BcryptTool from './bcrypt.class';(将自动从bcrypt.class模块导入default导出。但是,当使用import语句作为函数(称为"动态导入"(时,它将导入模块本身,而不是默认导出。

当您将console.log(BcryptTool)同时导入时,您可以看到差异:

  • import BcryptTool from './bcrypt.class'将显示{ default: { [Function: BcryptTool] hashValue: [Function], compare: [Function] } }
  • const BcryptTool = await require('bcrypt.class')将显示{ [Function: BcryptTool] hashValue: [Function], compare: [Function] }

您注意到第一个console.log中的default了吗?这显示您导入了模块,而不是默认模块。

实际上,import BcryptTool from './bcrypt.class'语法是做import { default as BcryptTool } from './bcrypt.class'的语法糖。如果你将这些知识应用于动态导入,你可以这样做:

const BcryptToolModule = await import('./bcrypt.class');
BcryptToolModule.default.compare(...);

或者用更简洁的语法:

const { default: BcryptTool } = await import('./bcrypt.class');
BcryptTool.compare(...);

最新更新