我试图理解为什么 Next.js 将我的一些页面构建为 SSG,而其中一些页面构建为静态,而它们都使用 getStaticProps。
让我们以我的 404 页面为例,该页面使用 getStaticProps 从带有 graphql 的棱镜中获取数据。它被呈现为静态网站,而我认为它应该呈现为 SSG(因为它使用 getStaticProps)。
我在我的 500 页中做完全相同的事情,但使用不同的 graphql 查询并且它被呈现(在我看来是正确的)作为 SSG。
这是为什么?
404 页面:
const NotFound = ({ data: { page } }) => {
return (
<div className={'not-found'}>
<p className={'not-found__description'}>{RichText.asText(page.description)}</p>
</div>
);
};
export const getStaticProps = async (context) => {
const currentLanguage = getCurrentLocale(context);
const response = await apolloClient.query({
query: gql`
query {
}
`
};
return {
props: {
data: {
page: response
}
}
}
});
export default NotFound;
500 页:
const InternalServerError = ({ data: { page } }) => {
return (
<div className={'internal-server-error'}>
<p className={'internal-server-error__description'}>{RichText.asText(page.description)}</p>
</div>
);
};
export const getStaticProps = async (context) => {
const currentLanguage = getCurrentLocale(context);
const response = await apolloClient.query({
query: gql`
query {
}
`
});
return {
props: {
data: {
page: response
}
}
}
};
答案 0 :(得分:4)
Next.js 中的 404.tsx 或 404.js 页面的独特之处在于它不依赖于服务器并且始终是静态的——仅依赖于静态 html(无 json)在构建时 -- 即使在文件中使用 GetStaticProps
。
404 页面只是一个捕获所有 funnel
路由,当用户导航到您的网站不存在的路径作为基本 URL 时,用户会重定向到该路由。因此,它在初始构建时不依赖于服务器。这是不存在的路径的后备,没有别的。另一方面,500 页处理应用程序中的内部错误,因此它确实依赖 .html
和 .json
文件类型来查明错误的性质。
有趣的是,如果您在本地检查 .next
目录的内容,您会注意到所有使用 GetStaticProps
的页面都静态生成了 .json
和 .html
文件。使用 GetStaticProps
和 revalidate
的页面返回 === Incremental Static Regeneration
或 ISR
。 ISR
是 SSG
和 SSR
的理想混合体,具有后台功能扫描生产中的传入更改/更新(您指定的数字是可能更新之间的时间量(以秒为单位))。因此,带有 GetStaticProps
+ ISR
的页面会在 .next
目录中生成三种文件类型——.html
、.json
和 .js
。也就是说,使用 GetServerSideProps
或 GetInitialProps
的页面在 .js
目录中只生成了 .next
个文件。最后,纯 Static
页面,不使用上述任何方法,仅生成 .html
文件。
404 页面背后的理念及其静态特性是通过加快自定义 oops! that path doesn't exist
页面的呈现(或更准确地说是预呈现)来增强用户体验,以便用户可以尽快返回实际应用。>
例如,我的 404.tsx
页面中有以下内容,但它仍然呈现为静态 html
在构建时。
import { Container } from '@/components/UI';
import { initializeApollo, addApolloState } from '@/lib/apollo';
import { NotFound } from '@/components/NotFound';
import { AppLayout } from '@/components/Layout';
import {
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType
} from 'next';
import {
NotFoundQuery,
NotFoundDocument,
NotFoundQueryVariables,
DynamicNavQuery,
DynamicNavDocument,
DynamicNavQueryVariables,
WordpressMenuNodeIdTypeEnum,
WordpressMediaItemSizeEnum,
WordpressPageIdType
} from '@/graphql/generated/graphql';
export function SOS({
notFound,
Header,
Footer
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<AppLayout title={'✂ 404 ✂'} Header={Header} Footer={Footer}>
<Container clean className='fit'>
<NotFound notFound={notFound} />
</Container>
</AppLayout>
</>
);
}
export async function getStaticProps(
ctx: GetStaticPropsContext
): Promise<
GetStaticPropsResult<{
notFound: NotFoundQuery['NotFound'];
Header: DynamicNavQuery['Header'];
Footer: DynamicNavQuery['Footer'];
}>
> {
const params = ctx.params!;
console.log(params ?? '');
const apolloClient = initializeApollo();
await apolloClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idTypeHead: WordpressMenuNodeIdTypeEnum.NAME,
idTypeFoot: WordpressMenuNodeIdTypeEnum.NAME,
idFoot: 'Footer'
}
});
await apolloClient.query<NotFoundQuery, NotFoundQueryVariables>(
{
query: NotFoundDocument,
variables: {
id: '/404-not-found/' as '/404/',
idType: WordpressPageIdType.URI,
size: WordpressMediaItemSizeEnum.LARGE
}
}
);
return addApolloState(apolloClient, {
props: {},
revalidate: 60
});
}
export default SOS;
有趣的是,因为我确实在我的 GetStaticProps
页面中将 revalidate
和 ISR
用于 404.tsx
,.next
目录的内容反映了这三个404
(.js, .json, .html
) 存在文件类型。如果您在自定义 getInitialProps
或 _app.tsx
文件中使用 _app.js
,则整个应用程序中的自动静态优化(静态页面的预呈现)将被禁用。如果您好奇,请尝试一下,它应该会导致 404 页面在您的构建日志中旁边有一个 lambda。但是,由于您已经拥有 GetStaticProps
,它应该使用 app
GetInitialProps
页面引起的应用程序范围的静态去优化
例如,前段时间我在创建自定义 GetInitialProps
页面之前在 _app.tsx
中使用了 404.tsx
。我决定拉取构建日志并拍摄随附的屏幕截图。
Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`.
答案 1 :(得分:0)
您的代码中的 404 页面是否缺少括号?
const response = await apolloClient.query({
query: gql`
query {
}
`
};
应该
const response = await apolloClient.query({
query: gql`
query {
}
`
});