Firebase SDK for Cloud Functions 升级指南:从测试版到 1.0 版或 2.0 版

Firebase SDK for Cloud Functions 1.0.0 版在 API 中引入了一些重要更改。主要更改是用 datacontext 参数代替了 event.data 格式,这会影响到所有异步(非 HTTP)函数。更新后的 SDK 也可与 firebase-functions-test(一种全新的单元测试配套 SDK)配合使用。如需了解详情,请参见单元测试函数

Firebase SDK for Cloud Functions 2.0.0 版针对 Firestore 触发的函数中的时间戳引入了一项重大更改。

要将 SDK 更新到最新版本,请在函数文件夹中运行以下命令:

npm install firebase-functions@latest --save
npm install firebase-admin@latest --save-exact

您还应该将 Firebase CLI 更新到最新版本:

npm install -g firebase-tools

会影响所有异步(非 HTTP)函数的 SDK 更改

按触发器类型分类的 SDK 更改

新版和旧版 API 参考

对函数模拟的更改

会影响所有后台(非 HTTP)函数的 SDK 更改

event 参数被拆分为 data 和 context

从 Firebase SDK for Cloud Functions 1.0 版开始,异步函数的 event 参数已作废。它已被两个新的参数取代:datacontext

data 参数表示触发了该函数的数据。data 参数中的字段由触发器类型决定,不同的类型对应不同的字段。例如,对于实时数据库,data 参数就是一个 DataSnapshot。如需详细了解 data 参数,请参阅按触发器类型分类的更改

context 参数提供有关函数执行情况的信息。在各种不同的异步函数类型中,context 所包含的字段是一样的,即 eventIdtimestampeventTyperesourceparams。此外,实时数据库函数会提供触发了该函数的用户的身份验证信息。以下示例展示了由一次实时数据库写入操作触发的函数中定义的上下文字段:

exports.dbWrite = functions.database.ref('/path/with/{id}').onWrite((data, context) => {
  const authVar = context.auth; // Auth information for the user.
  const authType = context.authType; // Permissions level for the user.
  const pathId = context.params.id; // The ID in the Path.
  const eventId = context.eventId; // A unique event ID.
  const timestamp = context.timestamp; // The timestamp at which the event happened.
  const eventType = context.eventType; // The type of the event that triggered this function.
  const resource = context.resource; // The resource which triggered the event.
  // ...
});

firebase-admin 的新初始化语法

现在,在 Cloud Functions 运行时中,firebase-admin 无需任何参数即可初始化。

旧版(0.9.1 或更早的版本)

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

新版(1.0.0 或更高版本)

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

请注意,您在进行初始化时不能再传入 functions.config().firebase 了。如需详细了解在 1.0.0 版中如何访问配置,请参阅以下部分。

移除了 functions.config().firebase

functions.config().firebase 已被移除。如果您想在自己的 Firebase 项目中访问配置值,可以改用 process.env.FIREBASE_CONFIG

let firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG);
/* {  databaseURL: 'https://databaseName.firebaseio.com',
       storageBucket: 'projectId.appspot.com',
       projectId: 'projectId' }
*/

按触发器类型分类的 SDK 更改

1.0 版为许多受支持的函数触发器引入了对数据字段和方法的命名方式的更改。本部分将按触发器类型列出这些更改。

实时数据库

事件数据现在是一个 DataSnapshot

在早期版本中,event.data 是一个 DeltaSnapshot;而在现在的 1.0 版中,它是一个 DataSnapshot

对于 onWriteonUpdate 事件,数据参数中含有 beforeafter 字段。每个字段都是一个 DataSnapshot,其中包含的方法与 admin.database.DataSnapshot 中提供的方法相同。例如:

旧版(0.9.1 或更早的版本)

exports.dbWrite = functions.database.ref('/path').onWrite((event) => {
  const beforeData = event.data.previous.val(); // data before the write
  const afterData = event.data.val(); // data after the write
});

新版(1.0.0 或更高版本)

exports.dbWrite = functions.database.ref('/path').onWrite((change, context) => {
  const beforeData = change.before.val(); // data before the write
  const afterData = change.after.val(); // data after the write
});

对于 onCreate 事件,数据参数是一个表示刚刚添加的数据的 DataSnapshot

旧版(0.9.1 或更早的版本)

exports.dbCreate = functions.database.ref('/path').onCreate((event) => {
  const createdData = event.data.val(); // data that was created
});

新版(1.0.0 或更高版本)

exports.dbCreate = functions.database.ref('/path').onCreate((snap, context) => {
  const createdData = snap.val(); // data that was created
});

对于 onDelete 事件,数据参数是一个表示刚刚删除的数据的 DataSnapshot

旧版(0.9.1 或更早的版本)

exports.dbDelete = functions.database.ref('/path').onDelete((event) => {
  const deletedData = event.data.previous.val(); // data that was deleted
});

新版(1.0.0 或更高版本)

exports.dbDelete = functions.database.ref('/path').onDelete((snap, context) => {
  const deletedData = snap.val(); // data that was deleted
});

用于用户身份验证信息的新属性

EventContext.auth V1.0.0 版引入了两个新的属性,用于访问触发函数的用户的信息(包括权限)。

  • EventContext.auth。包含 uid 和经过身份验证的用户的身份验证令牌等信息。
  • EventContext.authType。包含权限级别,例如,可以让您检测用户是否为管理员用户。

使用未记录的 event.auth 字段的开发者应更新相关代码,方能使用这些新属性。

adminRef 被替换为 ref

现在,.adminRef 引用已被移除,取而代之的是 .ref 引用,该引用现在被授予了管理员权限。系统不再支持之前使用 .ref 的方式(即用作对更改的引用,该更改是由触发了更改的用户授权的)。

旧版(0.9.1 或更早的版本)

exports.dbCreate = functions.database.ref('/path/{uid}').onCreate((event) => {
  const parentRef = event.data.adminRef.parent; // The Database reference to the parent authorized with admin privileges.

  const parentRefAsUser = event.data.ref.parent; // The Database reference to the parent authorized as the user which triggered the change.
});

新版(1.0.0 或更高版本)

exports.dbCreate = functions.database.ref('/path/{uid}').onCreate((snap, context) => {
  const parentRef = snap.ref.parent; // The Database reference to the parent authorized with admin privileges
});

您仍然可以使用 Admin SDK 对实时数据库执行由用户授权的更改:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

Cloud Firestore

就像 1.0 版中的实时数据库更改一样,onWriteonUpdate 也有一个包含 beforeafter 字段的数据参数。onCreateonDelete 事件都有一个数据参数,它是一个 Cloud Firestore DocumentSnapshot

旧版(0.9.1 或更早的版本)

exports.dbWrite = functions.firestore.document('/doc/path').onWrite((event) => {
  const beforeData = event.data.previous.data(); // data before the write
  const afterData = event.data.data(); // data after the write
});

新版(1.0.0 或更高版本)

exports.dbWrite = functions.firestore.document('/doc/path').onWrite((change, context) => {
  const beforeData = change.before.data(); // data before the write
  const afterData = change.after.data(); // data after the write
});

onCreateonDelete 事件都有一个数据参数,该参数是一个 DocumentSnapshot

旧版(0.9.1 或更早的版本)

exports.dbDelete = functions.firestore.document('/doc/path').onDelete((event) => {
  const deletedData = event.data.previous.data(); // data that was deleted
});

新版(1.0.0 或更高版本)

exports.dbDelete = functions.firestore.document('/doc/path').onDelete((snap, context) => {
  const deletedData = snap.data(); // data that was deleted
});

2.0.0 版中针对 Firestore 时间戳引入的重大更改

自 Firebase SDK for Cloud Functions 2.0.0 版开始,在函数内部接收的 Firestore 快照中的时间戳值为 Firestore 时间戳对象。这适用于 snapshot.createTimesnapshot.updateTimesnapshot.readTime 以及 snapshot.data() 中的所有时间戳值。

新版(2.0.0 版或更高版本)

exports.dbCreate = functions.firestore.document('/doc/path').onCreate((snap, context) => {
  //seconds of UTC time since Unix epoch
  console.log(snap.createTime.seconds);

  //fractions of a second at nanosecond resolution, 0 to 999,999,999
  console.log(snap.createTime.nanoseconds);
});

身份验证

在早期版本中,event.data.metadata 包含了现已弃用的字段 createdAtlastSignedInAt。1.0 版则完全移除了这些字段,并用 userRecord.metadata 参数中的 creationTimelastSignInTime 字段作为替代。

旧版(0.9.1 或更早的版本)

// This code won't work with Cloud Functions SDK 1.0 and higher!
exports.authAction = functions.auth.user().onCreate((event) => {
  const userMetadata = event.data.metadata;

  const creationTime = userMetadata.createdAt; // 2016-12-15T19:37:37.059Z
  const lastSignInTime = userMetadata.lastSignedInAt; // 2018-01-03T16:23:12.051Z
}

新版(1.0.0 或更高版本)

exports.authAction = functions.auth.user().onCreate((userRecord, context) => {
  const creationTime = userRecord.metadata.creationTime; // 2016-12-15T19:37:37.059Z
  const lastSignInTime = userRecord.metadata.lastSignInTime; // 2018-01-03T16:23:12.051Z
}

Crashlytics

在 1.0 版中,每当发生新问题时都会触发的事件处理程序是 onNew。之前名为 onNewDetected 的处理程序已被移除。

旧版(0.9.1 或更早的版本)

exports.newIssue = functions.crashlytics.issue().onNewDetected((event) => {
  const issue = event.data;

  const issueId = issue.issueId;
  const issueTitle = issue.issueTitle;
  const appName = issue.appInfo.appName;
  const appId = issue.appInfo.appId;
  const appPlatform = issue.appInfo.appPlatform;
  const latestAppVersion = issue.appInfo.latestAppVersion;
  const createTime = issue.createTime;
}

新版(1.0.0 或更高版本)

exports.newIssue = functions.crashlytics.issue().onNew((issue, context) => {
  const issueId = issue.issueId;
  const issueTitle = issue.issueTitle;
  const appName = issue.appInfo.appName;
  const appId = issue.appInfo.appId;
  const appPlatform = issue.appInfo.appPlatform;
  const latestAppVersion = issue.appInfo.latestAppVersion;
  const createTime = issue.createTime;
}

存储

onChange 事件处理程序已被移除。1.0 版已改为支持以下这些事件:

  • onArchive:仅在存储分区已启用对象版本控制时发送。此事件表明某个对象的当前活动版本已成为归档版本,原因可能是它被归档了,或者有新上传的同名对象导致它被覆盖了。
  • onDelete:当某个对象被永久删除时发送。这包括在存储分区的生命周期配置过程中被覆盖或删除的对象。对于已启用对象版本控制的存储分区,当某个对象被归档(参见 onArchive)时,系统不会发送此事件,即使通过 storage.objects.delete 方法进行归档也是如此。
  • onFinalize:当存储分区中成功创建了新对象(或现有对象的新实例)时发送。这包括复制或重写现有的对象。如果上传失败,则不会触发此事件。
  • onMetadataUpdate:当现有对象的元数据发生更改时发送。

旧版(0.9.1 或更早的版本)

exports.processFile = functions.storage.object().onChange((event) => {
  const object = event.data;

  const filePath = object.name; // Path of the File
  const contentType = object.contentType; // Mime type of the file

  // Exit if this is a deletion event.
  if (object.resourceState === 'not_exists') {
    console.log('This file was deleted.');
    return null;
  }

  // Exit if file exists but is not new and is only being triggered
  // because of a metadata change.
  if (resourceState === 'exists' && metageneration > 1) {
    console.log('This is a metadata change event.');
    return null;
  }

  // ...
}

新版(1.0.0 或更高版本)

exports.processFile = functions.storage.object().onFinalize((object, context) => {
  const filePath = object.name; // Path of the File
  const contentType = object.contentType; // Mime type of the file

  // ...
}

exports.fileDeleted = functions.storage.object().onDelete((object, context) => {
  console.log('This file was deleted.');
}

exports.metadataUpdated = functions.storage.object().onMetadataUpdate((object, context) => {
  console.log('This is a metadata change event.');
}

新版和旧版 API 参考

如需了解详情,请参阅 firebase-functions v1.0.0 的 API 参考。您还可以参阅 v0.9.1 的 API 参考以帮助您进行升级。

对函数模拟的更改

  • firebase serve 现在默认提供 HTTP 函数和托管服务。
  • 用于模拟所有函数的 firebase experimental:functions:shell 已被重命名为 firebase functions:shell

函数 shell 的语法更改

通过函数 shell 调用函数的语法已更新,以体现 firebase-functions 1.0.0 版的语法。

// Inside functions shell

// To emulate database writes done by an administrative user:
myDbFunction(‘data’)

// To emulate database writes done by an authenticated user:
myDbFunction(‘data’, { auth: { uid: ‘abc’ }})

// To emulate database writes done by an unauthenticated user:
myDbFunction(‘data’, { authMode: ‘UNAUTHENTICATED’)

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面