Gatsby混合应用-使用“ createPage”中的模板构建的页面上的子路由问题

时间:2019-08-09 08:18:32

标签: javascript reactjs routing gatsby reach-router

编辑: 我忘了提一下,我的网站包含大约25k用此模板构建的页面。 Derek Nguyen的答案将适用于页面数量较少的较小站点,但是当按比例放大时,matchPath数据将存储在JS中,从而导致大量的捆绑包。 (对我来说大约3.1mb!)

挑战

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

问题

我有一个createPage方法中用于静态HTML生成的模板组件,还有pages/目录中的一个组件,该组件用于将matchPath分配给仅客户端路由

在最新版本的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>

我也在此codesandbox中复制了行为。确保转到https://hkhbb.sse.codesandbox.io/test/foo/bar以查看正确的输出。

我已经在github中创建了一个issue,但是还没有得到答复。

1 个答案:

答案 0 :(得分:0)

问题

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

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

潜在的解决方案

在这种情况下,您需要做的都是同时为动态路由设置 /test/test/foo/bar根页面。这样,诸如/test/one/two之类的随机匹配将成为/test的动态路由;而/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.js移到了templates/template.js,我为pages/test.js添加了一个虚拟组件,以表明它仍然可以处理其他动态路由:

此外,如果您决定这样做,请注意此'wont-fix' bug