Closed roeean closed 2 years ago
@roeean The problem with getInitialProps
is that they are called on the server side so, there is no client side context. In this case you cannot use any hooks there.
Also bear in mind that getInitialProps
will disable Automatic Static Optimization.
If you want to fetch the menus, GQty will handle that for you at build time so there is no need to use getInitialProps
.
Take a look at the relevant component:
When you load the page you will see that there are no client side requests happening. The request happens once on the server at build time.
What you may want to test is having a common layout component as described in this post:
https://nextjs.org/docs/basic-features/layouts
If your page props do not change then the header will not re-render as well.
Additionally you could just create a header component, use the useQuery
hook to get the menus and render them in place. This is what we do in the example/getting-started
project, although we require the generalSettings
info
export default function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<FaustProvider client={client} pageProps={pageProps}>
<Header />
<Component {...pageProps} />
</FaustProvider>
</>
);
}
@theodesp If you were to move <Header />
outside of the <Component />
tree, as you have in your last snippet, each call to useQuery from within <Header />
would happen on the client side. It seems only calls to useQuery from within a page (that uses getNextStaticProps) will be statically cached.
Correct me if I'm wrong?
If I'm correct, is there a way to do what you've suggested in your last snippet? To have a global layout that exists outside of the rendered page (headers, footers) that request their own data that is statically cached at build/regen time?
@richardcalahan I think gqty does capture the requests happening in the server side so there are no CSR requests happening by default. If you look at the getting-started example project all of the content is rendered statically with 900 seconds invalidation: https://faustjs.org/docs/next/guides/ssr-ssg#setting-up-incremental-static-regeneration-isr
You can verify that when you do a production build and then run the next export
which creates static html files. For example this is the static html generated at build time for the getting-started example /posts
page:
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>myBlog - Just another WordPress site</title>
<meta name="next-head-count" content="3" />
<link rel="preload" href="/_next/static/css/5c54c503f8732a50.css" as="style" />
<link rel="stylesheet" href="/_next/static/css/5c54c503f8732a50.css" data-n-g="" />
<link rel="preload" href="/_next/static/css/f550fd9896487ad8.css" as="style" />
<link rel="stylesheet" href="/_next/static/css/f550fd9896487ad8.css" data-n-p="" />
<noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script>
<script src="/_next/static/chunks/webpack-3997a95a90267402.js" defer=""></script>
<script src="/_next/static/chunks/framework-5f4595e5518b5600.js" defer=""></script>
<script src="/_next/static/chunks/main-1038209226d7adb4.js" defer=""></script>
<script src="/_next/static/chunks/pages/_app-2e4cb5b4461bafa1.js" defer=""></script>
<script src="/_next/static/chunks/250-041c501ac42cc543.js" defer=""></script>
<script src="/_next/static/chunks/pages/posts-83c45a42c1083aa5.js" defer=""></script>
<script src="/_next/static/pt62k4m3DC6gM95ft__vB/_buildManifest.js" defer=""></script>
<script src="/_next/static/pt62k4m3DC6gM95ft__vB/_ssgManifest.js" defer=""></script>
</head>
<body>
<div id="__next" data-reactroot="">
<header>
<div class="Header_wrap__R9imJ">
<div class="Header_title-wrap__4e17x">
<p class="Header_site-title__Otw1K">
<a href="/">myBlog</a>
</p>
<p class="Header_description__EJ3Db">Just another WordPress site</p>
</div>
<div class="Header_menu__6BMG0">
<ul>
<li>
<a href="http://localhost:3000/sample-page/">Sample Page</a>
</li>
<li>
<a class="button" href="https://github.com/wpengine/faustjs">GitHub</a>
</li>
</ul>
</div>
</div>
</header>
<main class="content content-index">
<section id="posts_post_list__glOzP">
<div class="wrap">
<h2>Blog Posts</h2>
<div class="posts">
<div class="Posts_single__rpTye" id="post-cG9zdDoyMw==">
<div>
<h3 class="Posts_title__q_vy3">
<a href="/posts/example-post">Example Post</a>
</h3>
<div>
<p>Hello This is a Header Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, […]</p>
</div>
<a aria-label="Read more about function ProxyFn(argValues = emptyVariablesObject) {
return resolve({
argValues,
argTypes: __args
});
}" href="/posts/example-post">Read more</a>
</div>
</div>
<div class="Posts_single__rpTye" id="post-cG9zdDox">
<div>
<h3 class="Posts_title__q_vy3">
<a href="/posts/hello-world">Hello world!</a>
</h3>
<div>
<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing! Welcome to WordPress. This is your first post. Edit or delete it, then start writing! Heading Hello</p>
</div>
<a aria-label="Read more about function ProxyFn(argValues = emptyVariablesObject) {
return resolve({
argValues,
argTypes: __args
});
}" href="/posts/hello-world">Read more</a>
</div>
</div>
</div>
</div>
</section>
<nav class="pagination" aria-label="Pagination">
<div class="wrap">
<ul></ul>
</div>
</nav>
</main>
<footer class="Footer_main__SP1FG">
<div class="Footer_wrap__4e6e3">
<p>© 2022 myBlog. All rights reserved.</p>
</div>
</footer>
</div>
<script id="__NEXT_DATA__" type="application/json">
{
"props": {
"pageProps": {
"__CLIENT_CACHE_PROP": "{\"cache\":{\"generalSettings\":{\"__typename\":\"GeneralSettings\",\"title\":\"myBlog\",\"description\":\"Just another WordPress site\"},\"menuItems_8d665_12a43\":{\"__typename\":\"RootQueryToMenuItemConnection\",\"nodes\":[{\"__typename\":\"MenuItem\",\"id\":\"cG9zdDoxNw==\",\"url\":\"http://localhost:3000/sample-page/\",\"label\":\"Sample Page\"}]},\"posts_f30bc_81560\":{\"__typename\":\"RootQueryToPostConnection\",\"nodes\":[{\"__typename\":\"Post\",\"id\":\"cG9zdDoyMw==\",\"slug\":\"example-post\",\"title_b28e9_bf21a\":\"Example Post\",\"excerpt_b28e9_bf21a\":\"\u003cp\u003eHello This is a Header Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, [\u0026hellip;]\u003c/p\u003e\\n\"},{\"__typename\":\"Post\",\"id\":\"cG9zdDox\",\"slug\":\"hello-world\",\"title_b28e9_bf21a\":\"Hello world!\",\"excerpt_b28e9_bf21a\":\"\u003cp\u003eWelcome to WordPress. This is your first post. Edit or delete it, then start writing! Welcome to WordPress. This is your first post. Edit or delete it, then start writing! Heading Hello\u003c/p\u003e\\n\"}],\"pageInfo\":{\"__typename\":\"WPPageInfo\",\"startCursor\":\"YXJyYXljb25uZWN0aW9uOjIz\",\"endCursor\":\"YXJyYXljb25uZWN0aW9uOjE=\",\"hasPreviousPage\":false,\"hasNextPage\":false}}},\"selections\":[[[\"{\\\"after\\\":\\\"String\\\",\\\"before\\\":\\\"String\\\",\\\"first\\\":\\\"Int\\\",\\\"last\\\":\\\"Int\\\",\\\"where\\\":\\\"RootQueryToPostConnectionWhereArgs\\\"}\",\"f30bc\"],[\"{\\\"first\\\":6}\",\"81560\"],[\"{\\\"after\\\":\\\"String\\\",\\\"before\\\":\\\"String\\\",\\\"first\\\":\\\"Int\\\",\\\"last\\\":\\\"Int\\\",\\\"where\\\":\\\"RootQueryToMenuItemConnectionWhereArgs\\\"}\",\"8d665\"],[\"{\\\"where\\\":{\\\"location\\\":\\\"PRIMARY\\\"}}\",\"12a43\"],[\"{\\\"format\\\":\\\"PostObjectFieldFormatEnum\\\"}\",\"b28e9\"],[\"{}\",\"bf21a\"]],\"v1\"]}",
"__AUTH_CLIENT_CACHE_PROP": "{}"
},
"__N_SSG": true
},
"page": "/posts",
"query": {},
"buildId": "pt62k4m3DC6gM95ft__vB",
"isFallback": false,
"gsp": true,
"scriptLoader": []
}
</script>
</body>
</html>
The menu items there are compiled at build time.
@theodesp correct, but in your last snippet i was referencing you suggested moving the <Header />
component out of the page and into the root of the <FaustProvider />
in _app.js
. I'd like to do something like that, but once you do the useQuery call only happens on the frontend.
The getting-started example has the <Header />
component in the page, which ensures its query is compiled at build time.
@richardcalahan yes you are right sorry my bad. Within the _app.tsx
component you cannot use getStaticProps
as it is not a page component and this is what Next.js mentions when you want to use data fetching in layouts
https://nextjs.org/docs/basic-features/layouts#data-fetching. In order to avoid this issue you can either:
GQty
hooks there, but you can use the fetch api sending
https://gqty.dev/docs/client/fetching-data#resolvedHere is a rough implementation:
import 'faust.config';
import { FaustProvider } from '@faustjs/next';
import 'normalize.css/normalize.css';
import React from 'react';
import 'scss/main.scss';
import { client } from 'client';
import type { AppProps } from 'next/app';
export default function MyApp({ Component, pageProps, menus }: AppProps) {
return (
<>
<FaustProvider client={client} pageProps={pageProps}>
<Component {...pageProps} />
</FaustProvider>
</>
);
}
MyApp.getInitialProps = async (ctx) => {
const res = await fetchMenusJSON();
return { menus: res?.data?.menuItems ?? {} };
};
async function fetchMenusJSON() {
const response = await fetch(`https://headlessfw.wpengine.com/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
query MenusQuery {
menuItems(where: {location: PRIMARY}) {
nodes {
id
url
label
}
}
}
`,
})
});
const menus = await response.json();
return menus;
}
I hope this helps.
Cool, yeah we've used both methods here and there in the past. They work well. Thanks for the help.
@roeean did the above options solved your issues yet?
@theodesp, Yes, the issue is solved, Thank you.
Hello,
First, thank you so much for the fantastic package you created! It has drastically improved the performance of my project and greatly facilitated the development and maintenance process.
I'm in the middle of building a Next.js app, and I need to make a request for the navigation content to my WPGraphQL, get the results, and pass them to my Header component so that I can have a persistent navigation menu. I don't want to include the header in every page component, nor do I want to have to query the document on every page.
Given that it is impossible to access getServerSideProps and getStaticProp within my _app.js, my only option is to add getInitialProps.
However, when I try to use faust.js in the _app file, I get the following error, probably because the request is sent before the initialization of the faust-client.
Do you have any idea how to solve this?
Thank you in advance,
my _app.js code:
the error: