Hoodie 和 React 入门

Avatar of Jake Peyser
Jake Peyser

DigitalOcean 为您旅程的各个阶段提供云产品。 立即开始使用 价值 200 美元的免费积分!

让我们来看一看 Hoodie,这个专门为前端开发人员构建的“后端即服务”(BaaS)。 我想解释一下,为什么我认为它是一个设计精良的工具,并且应该在竞争对手中获得比现在更多的关注。 我已经制作了一个演示,展示了该服务的某些关键功能,但我认为有必要先为它的用例设置场景。 如果你想获取代码,请随时 跳转到演示仓库。 否则,请与我一起简要概述一下。

设置场景

众所周知,JavaScript 正在吞噬世界。 随着其流行度的爆炸式增长,一个不断扩展的工具生态系统应运而生。 近年来,由于这些工具的出现,开发 Web 应用程序变得前所未有的容易。 开发者工具 PrettierESLint 使我们可以随意编写代码,并仍然输出干净的代码。 ReactVue 等框架为创建交互式体验提供了必不可少的模型。 WebpackBabel 等构建工具使我们能够使用最新、最强大的语言特性和模式,而不会牺牲速度和效率。

如今,JavaScript 的关注点似乎主要集中在前端工具上,但这并不意味着后端没有得到重视。 这种自动化和抽象模式在服务器端也同样适用,主要以我们所说的“后端即服务”(BaaS) 形式出现。 此模型为前端开发人员提供了一种方法,让他们将 Web 或移动应用程序链接到后端服务,而无需编写服务器代码。

这些服务中的许多已经存在了一段时间,但还没有真正出现赢家。 Parse 是该领域的早期参与者,于 2013 年被 Facebook 收购,并 随后关闭Firebase 被 Google 收购,并且正在逐步开拓市场份额。 就在几周前,MongoDB 宣布了他们自己的 BaaS,Stitch,希望借此利用其数据库的市场渗透率。

BaaS 优势

BaaS 选项非常多,但它们的核心都具有相同的优势。

  • 简化开发:没有自定义服务器的明显优势在于,它消除了开发服务器的必要性! 这意味着您的开发团队将减少上下文切换,最终可以腾出更多时间专注于核心逻辑。 不需要任何服务器语言知识!
  • 无需样板服务器:许多服务器最终的存在目的仅仅是连接客户端与相关数据。 这通常会导致大量的 Web 框架和 DAL 样板代码。 BaaS 模型消除了对这些重复代码的需求。

这些只是 BaaS 的主要优势。 Hoodie 提供了这些优势以及更多独特的功能,我们将在下一节中介绍。

试戴您的 Hoodie

为了展示 Hoodie 提供的一些开箱即用的功能,我将带您了解一个简单的 Markdown 笔记 Web 应用程序的几个部分。 它将处理用户身份验证、对用户笔记的完整 CRUD 操作以及在断开互联网连接时继续工作的能力。

您可以通过将 hoodie-notes GitHub 仓库 克隆到您的本地计算机并使用 README 中的说明运行它来按照代码进行操作。

本演练的重点是 hoodie-client 的实现,因此假设您已具备 React、Redux 和 ES6 的知识。 虽然这些知识有所帮助,但并非理解我们将在此处讨论的范围所必需。

基础知识

要开始使用 Hoodie,您实际上只需要做三件事。

  1. 将您的静态文件放置在项目根目录下的名为 /public 的文件夹中。 我们将我们的 index.html 以及所有转译后的 JS 和图像文件放在这里,以便它们可以公开给客户端。
  2. 在您的前端代码中初始化 Hoodie 客户端

    const hoodie = new Hoodie({
      url: window.location.origin,
      PouchDB: require('pouchdb-browser')
    })
  3. 通过在终端中运行 hoodie 来启动您的 Hoodie 服务器

当然,创建应用程序还需要做更多工作,但这些就是您入门所需的一切!

用户身份验证

Hoodie 使用户和会话管理变得异常简单。 账户 API 可用于创建用户、管理其登录会话以及更新其账户。 处理这些 API 调用的所有代码都存储在 user 减少器 中。

当我们的应用程序启动时,我们会看到一个登录屏幕,其中包含创建用户或登录的选项。

当按下这些按钮中的任何一个时,将分派相应的 Redux thunk 来处理身份验证。 我们使用 signUpsignIn 函数来处理这些事件。 若要创建新账户,我们将进行以下调用

hoodie.account.signUp({ username: 'guest', password: '1234' })
  .then(account => {
    // successful creation
  }).catch(err => {
    // account creation failure
  })

在系统中拥有账户后,我们可以在将来使用以下方法登录

hoodie.account.signIn({ username: 'guest', password: '1234' })
  .then(account => {
    // successful login
  }).catch(err => {
    // login failure
  })

现在我们有了用户身份验证、授权和会话管理,而无需编写一行服务器代码。 此外,Hoodie 在本地存储中管理会话,这意味着您可以刷新页面而无需重新登录。 若要利用这一点,我们可以在应用程序的初始渲染时执行以下逻辑

hoodie.account.get()
  .then({ session, username }=> {
    if (session)
      console.log(`${username} is already logged in!`)
  }).catch(err => {
    // session check failure
  })

若要注销,我们只需要调用 hoodie.account.signOut() 即可。 很酷!

CRUD 笔记

Hoodie 中关于用户管理最棒的一点是,所有在登录状态下创建的文档只能由该经过身份验证的用户访问。 授权完全从我们这里抽象出来,使我们能够专注于使用 存储 API 创建、检索、更新和删除文档的简单逻辑。 处理这些 API 调用的所有代码都存储在 notes 减少器 中。

让我们从创建一个新笔记开始

hoodie.store.add({ title: '', text: '' })
  .then(note => console.log(note))
  .catch(err => console.error(err))

我们可以将任何想要的对象传递给 add 函数,但在这里我们创建一个包含标题和文本字段的空笔记。 作为回报,我们将在 Hoodie 数据存储中获得一个新对象,其中包含其相应的唯一 ID 以及我们赋予它的属性。

当我们想要更新该文档时,只需要将该笔记与更新的(甚至新的)属性一起传递回去即可

hoodie.store.update(note)
  .then(note => console.log(note))
  .catch(err => console.error(err))

Hoodie 处理更新存储所需的全部差异和关联逻辑。 我们只需要将笔记传递给 update 函数。 然后,当用户选择删除该笔记时,我们将把它的 ID 传递给 remove 函数

hoodie.store.remove(note._id)
  .then(()=> console.log(`Removed note ${note._id}`))
  .catch(err => console.error(err))

最后我们要做的事情是在用户重新登录时检索我们的笔记。 由于我们只将笔记存储在数据存储中,因此我们可以使用 findAll 函数检索用户的全部文档

hoodie.store.findAll()
  .then(notes => console.log(notes))
  .catch(err => console.error(err))

如果需要,我们也可以使用 find 函数查找单个文档。

将所有这些调用组合在一起,我们实际上替换了一个 /notes REST API 端点,而该端点原本需要大量的样板请求处理和 DAL 代码。 你可能会说这是偷懒,但我认为我们是聪明地工作!

监控连接状态

Hoodie 是基于离线优先理念构建的,这意味着它假设客户端在会话期间会长时间处于离线状态。这种态度优先处理这些事件,使其不会产生错误,而是允许用户像往常一样继续工作,而不必担心数据丢失。此功能由PouchDB和巧妙的同步策略在幕后实现,但是,使用hoodie-client的开发者无需了解这些细节,因为所有这些都在后台处理。

我们将稍后看到这如何改善我们的用户体验,但首先让我们看看如何使用连接状态 API监控此连接。当应用程序首次渲染时,我们可以像这样在根组件上为连接状态建立监听器

componentDidMount() {
  hoodie.connectionStatus.startChecking({interval: 3000})
  hoodie.connectionStatus.on('disconnect', () => this.props.updateStatus(false))
  hoodie.connectionStatus.on('reconnect', () => this.props.updateStatus(true))
}

在这种情况下,我们告诉 Hoodie 定期检查我们的连接状态,然后附加两个监听器来处理连接变化。当这些事件中的任何一个触发时,我们更新 Redux 存储中的相应值,并相应地调整 UI 中的连接指示器。这就是我们提醒用户他们已断开与服务器连接所需的所有代码。

要测试这一点,请在浏览器中打开应用程序。您将在应用程序的左上角看到连接指示器。如果您在页面仍处于打开状态时停止服务器,您将在下一个间隔看到状态更改为“已断开连接”。

在您断开连接时,您可以继续添加、编辑和删除笔记,就像您平时一样。更改会保存在本地,Hoodie 会跟踪您离线时所做的更改。

准备好后,重新启动服务器,指示器将再次变回“已连接”状态。然后,Hoodie 会在后台与服务器同步,用户不会察觉到连接中断(当然,我们的指示器除外)。

如果您不相信它就这么简单,请刷新页面。您会发现您离线时创建的数据都在那里,就好像您从未断开连接一样。考虑到我们没有做任何事情来实现它,这真是太不可思议了!

为什么我喜欢 Hoodie

Hoodie 绝不是唯一的后端即服务 (BaaS) 提供商,但我认为它是一个很好的选择,原因有几个。

  1. 简单的 API:在本演练中,我们能够涵盖 Hoodie API 的 4 个中的 3 个。它们非常简单,没有太多多余的功能。我非常喜欢简单胜于复杂,直到后者无法避免,而 Hoodie 绝对符合这一要求。
  2. 免费且可自行托管:自己将 Hoodie 部署到生产环境中可能看起来很麻烦,但我相信这种服务会为您提供长期的保障。付费的托管服务需要您对该服务的可靠性和持久性进行押注(例如:Parse)。这一点,加上供应商锁定,让我在有意义的情况下倾向于自行托管。
  3. 开源:无需赘述……支持开源社区!
  4. 离线优先:Hoodie 为间歇性连接的相关问题提供了一个无缝解决方案,并为开发者减轻了实现负担。
  5. 插件:Hoodie 支持第三方插件,以提供对 API 范围之外的额外服务器端功能的支持。当您开始错过拥有自己服务器的灵活性时,它可以提供一些巧妙的解决方案。
  6. 理念:构建和支持 Hoodie 的开发者显然已经认真思考过该服务代表什么以及他们为什么要构建它。他们在开源项目中核心推崇开放、赋能和去中心化(以及其他方面),这很好。我爱它的一切!

注意事项

在您决定放弃服务器转而使用像 Hoodie 这样的 BaaS 之前,您应该考虑一些事项。

您更喜欢提高开发速度还是未来的灵活性?如果前者是您的优先事项,那么使用 BaaS!如果您真的关心性能和可扩展性,您可能最好自己启动服务器。这表明将 BaaS 用于 MVP 或轻量级应用程序,并为定义明确的复杂应用程序创建自定义服务器。

您的应用程序是否需要与任何第三方服务集成?如果是,您可能需要自己服务器的灵活性来实现自己的自定义实现逻辑,而不是限制自己使用 Hoodie 插件。

最后,Hoodie 的文档严重缺乏。它可以帮助您入门,但文档中缺少许多 API 定义,您需要自己填补一些空白。这可以通过界面经过精心设计这一事实来缓解。尽管如此,如果您习惯于完整的文档,这会带来令人沮丧的体验。

结论

对于前端开发者来说,在考虑创建 Web 应用程序的选项时,使用 BaaS 非常有前景。它避免了编写服务器逻辑和实现本质上相当于样板 REST API 的必要性。Hoodie 提供了这种可能性,并额外增加了干净的界面、简单的用户管理和离线优先功能。

如果您只需要一个简单的 CRUD 应用程序,请考虑在您的下一个应用程序中使用 Hoodie!

其他资源