3

编辑:我忘了提到我的网站包含从这个模板构建的大约 25k 页面。Derek Nguyen 的回答将适用于页面数量较少的小型网站,但是当扩大规模时,matchPath数据将存储在 JS 中,导致捆绑包大小很大。(对我来说大约 3.1mb!)

挑战

我需要创建一个页面,createPage其中包含一个子路由系统,其中默认路由构建为静态 HTML,但任何其他路由都是客户端专用的。

问题

我在方法中有一个用于静态 HTML 生成的模板组件createPage,还有一个pages/目录中的组件,用于为仅限客户端的路由分配一个matchPathto。

在最新版本的 Gatsby 上,模板组件为默认路由呈现,但随后“页面”组件为仅客户端呈现,当我只希望子路由呈现时,导致整页重新呈现,如父路由中有需要持久化的数据。

在我看来,有两个组件和两个路由器似乎是错误的,但我想不出任何其他方式来实现我想要实现的目标。

这是我的路由设置的示例:

模板用于createPage

<Router>
  <ContainerComponent
     path={urlFromGraphQL}
  >
    <DefaultRoute
      default
    />
  </ContainerComponent>
</Router>

仅客户端组件/pages

<Router>
  <ContainerComponent
     path="/some-route/:slug/:id"
  >
    <DefaultRoute
      default
    />
    <SecondTabRoute
      path="second-tab-route"
    />
    <ThirdTabRoute
      path="third-tab-route"
    />
  </ContainerComponent>
</Router>

我还复制了这个代码框中的行为。确保转到https://hkhbb.sse.codesandbox.io/test/foo/bar以查看正确的输出。

我在 github 上创建了一个关于此的问题,但还没有回复。

4

1 回答 1

1

问题

看起来您正在混合静态生成的页面和动态页面,即您在/test/foo/bar匹配时都test/:param1/:param2在生成页面test.js

静态生成的页面将比动态页面具有更高的特异性,因此 Gatsby 认为test/foo/bar&test/foo/bar/second-route是 2 个不同的页面,而不是来自同一个静态页面的 2 个动态路由。

潜在的解决方案

在这种情况下,您需要做的是为动态路由制作两个 /test&/test/foo/bar根页面。这样,随机匹配/test/one/two将成为/test; while/test/foo/bar/second-route将是 的动态路由/test/foo/bar

由于您已经/test/foo/bar以编程方式创建,因此将其作为动态页面的根是微不足道的:

  // gatsby-node.js
  exports.createPages = async ({ actions }) => {
    const { createPage } = actions
    const pathFromGraphQL = "/test/foo/bar"

    createPage({
      component: path.resolve(`./src/templates/template.js`),
      context: {
        url: pathFromGraphQL,
      },
      path: pathFromGraphQL,
+     matchPath: `${pathFromGraphQL}/*`,
    })
  }

现在的问题是“template.js”不再完全是模板,它必须包含特定于test/foo/bar. 根据您的要求,这可能是一个阻碍,也可能以某种方式被规避。

我稍微编辑你的叉子来证明这一点;除了上面的代码更改之外pages/test.jstemplates/template.js我还添加了一个虚拟组件,pages/test.js以显示它仍然可以处理其他动态路由:

此外,如果您决定这样做,请注意这个“不会修复”错误

于 2019-08-10T18:04:28.427 回答