编辑:
我忘了提一下,我的网站包含大约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,但是还没有得到答复。
答案 0 :(得分:0)
问题
看起来您正在混合静态生成的页面和动态页面,即,您都在/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
的动态路由;而/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。