amazeelabs/silverback_gatsby

在 Gatsby 和 Drupal 之间的桥接模块。


README

一个 Drupal 模块,为 Gatsby 插件 @amazeelabs/gatsby-source-silverback 提供集成端点。允许基于 GraphQL V4 编写自定义 GraphQL 模式定义,并自动将增量更新发送到 Gatsby。

重大更改

由于引入了对 graphql_directives 模块的新依赖,版本 2 中引入了一些重大更改。

  • @resolveEntityReference@resolveEntityReferenceRevisions 不再支持 single 参数。它们可以用 @seek 来链式调用。
  • Gutenberg 指令已移动到 silverback_gutenberg 模块,并在命名和参数上进行了更改。有关更多信息,请参阅生成的指令。
  • 新的默认值处理需要可空的自定义类型调用或它们上的 @default 指令。有关更多信息,请参阅 graphql_directives 模块。

入门

首先,简单地安装并启用该模块。

composer require amazeelabs/silverback_gatsby
drush en -y silverback_gatsby

在项目的根目录下创建一个 GraphQL 文件夹。这将包含所有的模式定义。为了提高 IDE 支持,您可以将所有的模式定义导出到一个文件中

drush graphql:directives > graphql/directives.graphqls

建议在版本控制中忽略此文件,并在需要时重新创建它。

现在,您可以使用提供的指令开始创建项目模式定义并填写解析器。

schema {
  query: Query
}

type Query {
  page(id: String!): Page @loadEntity(type: "node", id: "$id")
}

type Page @entity(type: "node", bundle: "page") {
  path: String! @resolveEntityPath
  title: String! @resolveEntityLabel
  body: String @resolveProperty(path: "body.value")
}

现在创建一个新的 GraphQL 服务器配置,使用 Directable 模式插件,并确保启用 "Silverback Gatsby" 扩展。在 资源管理器Voyager 界面中应该会显示用于加载和查询我们的类型(loadPagequeryPages)的根级别字段,现在您可以对其进行测试。

Gatsby 页面的自动创建

通过使用 @isPath@isTemplate 字段指令可用。有关详细信息,请参阅 @amazeelabs/gatsby-source-silverback 插件的 README。

自动解析器

有一些指令可以自动创建 GraphQL 解析器。

@resolveProperty

此字段指令是 property_path 数据生产器的快捷方式。

例如,以下模式

type Page @entity(type: "node", bundle: "page") {
  body: String @resolveProperty(path: "field_body.0.processed")
}

将为 Page.body 字段创建以下解析器

$builder->produce('property_path', [
  'path' => $builder->fromValue('field_body.0.processed'),
  'value' => $builder->fromParent(),
  'type' => $builder->fromValue('entity:node:page'),
])

@resolveEntityPath

解析到实体的相对路径。这是 entity_url+url_path 数据生产器的快捷方式。

示例

type Page @entity(type: "node", bundle: "page") {
  path: String! @resolveEntityPath
}

@resolveEntityReference

解析引用实体。这是 entity_reference 数据生产器的快捷方式。

示例

type Page @entity(type: "node", bundle: "page") {
  relatedArticles: [Article]! @resolveEntityReference(field: "field_related_articles", single: false)
  parentPage: Page @resolveEntityReference(field: "field_related_articles", single: true)
}

@resolveEntityReferenceRevisions

解析实体引用版本字段,例如段落。这是 entity_reference_revisions 数据生产器的快捷方式。

示例

type Page @entity(type: "node", bundle: "page") {
  paragraphs: [PageParagraphs!]! @resolveEntityReferenceRevisions(field: "field_paragraphs", single: false)
  singleParagraph: ParagraphText @resolveEntityReferenceRevisions(field: "field_single_paragraph", single: true)
}

菜单

要公开 Drupal 菜单给 Gatsby,可以使用 @menu 指令。

type MainMenu @menu(menu_id: "main") {
  items: [MenuItem!]! @resolveMenuItems
}

type MenuItem {
  id: String! @resolveMenuItemId
  parent: String! @resolveMenuItemId
  label: String! @resolveMenuItemLabel
  url: String! @resolveMenuItemUrl
}

GraphQL 不允许递归片段,所以像这样的事情是不可能的

query Menu {
  drupalMainMenu {
    items {
      ...MenuItem
    }
  }
}
fragment MenuItem on MenuItem {
  label
  url
  children {
    # Fragment recursion, not allowed in GraphQL!
    ...MenuItem
  }
}

因此,菜单树会自动展开,并为每个项添加 idparent 属性,以便在消费应用程序中轻松重建树。

query MainMenu {
  drupalMainMenu(langcode: { eq: "en" }) {
    items {
      id
      parent
      label
      url
    }
  }
}

《@menu》指令还可以接受一个可选的《max_level》参数。它可以用来限制类型包含的层级数量,从而优化缓存和Gatsby构建时间。在许多情况下,主页布局只显示菜单项的第一层。当创建一个新页面并将其附加到第三层时,Gatsby仍然会重新渲染所有页面,因为用于页眉的菜单已更改。通过将其分为两个层级,我们可以确保外层布局仅在显示的菜单层级改变时才真正改变。

type MainMenu @menu(menu_id: "main") {...}
# Will only include the first level and trigger updates when a first level item
# changes.
type LayoutMainMenu @menu(menu_id: "main", max_level: 1) {...}

菜单协商

在某些情况下,相同的GraphQL字段可能需要根据当前上下文返回不同的菜单。一个典型的用例是多个站点设置,其中应显示不同的菜单,这取决于Gatsby当前使用以获取数据的账户。

在这种情况下,可以将多个菜单ID传递给《@menu》指令,并且解析器将选择用户账户可访问的第一个。

type MainMenu
  @menu(menu_ids: ["site_a_main", "site_b_main"], item_type: "MenuItem")

它检查对《Menu》实体上的《view label》操作的可访问性,默认情况下允许所有人访问。消费项目必须实现其他机制来限制访问,从而控制用于哪个站点的菜单。

配置更新通知

最后要做的就是告诉Gatsby何时发生值得注意的变化。通过在我们的模式中使用《@entity》指令,我们已经告诉Drupal跟踪与我们关心的实体类型相关的所有更改。所缺少的只是一个Gatsby webhook url来触发刷新。我们通过一个以我们配置的GraphQL服务器命名的环境变量提供此内容。

GATSBY_BUILD_HOOK_[uppercased-server-id]=https://...

因此,如果服务器被命名为《My Server》并且自动生成的机器名称是《my_server》,则环境变量将如下所示

GATSBY_BUILD_HOOK_MY_SERVER=https://...

该值是一个分号分隔的URL列表,在更新发生时将被调用。这可以是用于本地测试Gatsby环境的《https://:8000/__refresh》,或者Gatsby Cloud提供的构建和预览webhooks。

为了使此功能生效,Gatsby站点必须包含@amazeelabs/gatsby-source-silverback插件。

访问控制

默认情况下,@amazeelabs/gatsby-source-silverback表现得像匿名用户。要更改这一点,只需创建一个具有所需权限的用户账户,并将凭证传递给插件的《auth_user》和《auth_pass》配置选项。

一个非常常见的用例是创建一个“预览”用户,它绕过内容访问控制,并用于Gatsby云上的“预览”环境,以便可以预览未发布的内容。另一个合理的用例是创建一个“构建”用户,该用户可以访问发布的内容,并阻止对Drupal的匿名访问。

触发构建

有几种方法可以触发Gatsby构建

  • 在实体保存时
  • 通过Drupal UI或Drush。

在实体保存时

在模式配置的《构建》选项卡上,勾选《在实体保存时触发构建》复选框。

Drupal UI

在同一个《构建》选项卡上,单击《Gatsby构建》按钮。

Drush

此命令可以在系统cron中配置。drush silverback-gatsby:build [server_id]