Next.js 没有在应该将页面构建为 SSG 时
Next.js is not building page as SSG when it should
我想了解为什么 Next.js 将我的一些页面构建为 SSG,将其中一些构建为静态,而它们都使用 getStaticProps。
让我们以我的 404 页面为例,该页面使用 getStaticProps 通过 graphql 从 prismic 获取数据。它呈现为静态网站,而在我看来它应该呈现为 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
}
}
}
};
404 页面是否缺少代码中的括号?
const response = await apolloClient.query({
query: gql`
query {
}
`
};
应该是
const response = await apolloClient.query({
query: gql`
query {
}
`
});
Next.js 中的 404.tsx 或 404.js 页面是独一无二的,因为它不依赖于服务器并且始终是静态的——仅依赖于静态 html (无 json)在构建时——即使在文件中使用 GetStaticProps
。
404 页面只是一个包罗万象的 funnel
路由,当用户导航到以您的站点为基础 URL 时不存在的路径时,用户将被重定向到该路由。因此,它在初始构建时不依赖于服务器。这是不存在路径的回退,仅此而已。另一方面,500 页面处理应用程序中的内部错误,因此它 依赖 .html
和 .json
文件类型来查明错误的性质错误。
有趣的是,如果您在本地检查 .next
目录的内容,您会注意到所有使用 GetStaticProps
的页面都有静态生成的 .json
和 .html
文件.使用 GetStaticProps
和 revalidate
returned === Incremental Static Regeneration
或 ISR
的页面。 ISR
是 SSG
和 SSR
的理想混合体,具有后台功能扫描生产中传入的 changes/updates(您指定的数字是可能更新之间的时间量(以秒为单位) ).因此,带有 GetStaticProps
+ ISR
的页面会在 .next
目录中生成三种文件类型——.html
、.json
和 .js
。也就是说,使用 GetServerSideProps
或 GetInitialProps
的页面只会在 .next
目录中生成 .js
个文件。最后,纯Static
的页面,使用上述方法none,只生成了.html
个文件。
404 页面及其静态特性背后的想法是通过加快自定义 oops! that path doesn't exist
页面的呈现(或更正确的预呈现)来增强用户体验,以便用户可以 return尽快实际申请。
例如,我的 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;
有趣的是,因为我在 404.tsx
页面中使用 GetStaticProps
和 revalidate
作为 ISR
,.next
目录的内容反映了这一点404
(.js, .json, .html
) 所有三种文件类型都存在。如果您在自定义 _app.tsx
或 _app.js
文件中使用 getInitialProps
,则整个应用程序的自动静态优化(静态页面的预呈现)将被禁用。如果您好奇,请尝试一下,它应该会导致 404 页面在您的构建日志中旁边有一个 lambda。但是,由于您已经有 GetStaticProps
,它应该使用 GetInitialProps
覆盖由根 app
页面引起的应用程序范围内的静态去优化
例如,在创建自定义 404.tsx
页面之前,我在 _app.tsx
中使用了 GetInitialProps
。我决定提取构建日志并拍摄随附的屏幕截图。
Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`.
我想了解为什么 Next.js 将我的一些页面构建为 SSG,将其中一些构建为静态,而它们都使用 getStaticProps。
让我们以我的 404 页面为例,该页面使用 getStaticProps 通过 graphql 从 prismic 获取数据。它呈现为静态网站,而在我看来它应该呈现为 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
}
}
}
};
404 页面是否缺少代码中的括号?
const response = await apolloClient.query({
query: gql`
query {
}
`
};
应该是
const response = await apolloClient.query({
query: gql`
query {
}
`
});
Next.js 中的 404.tsx 或 404.js 页面是独一无二的,因为它不依赖于服务器并且始终是静态的——仅依赖于静态 html (无 json)在构建时——即使在文件中使用 GetStaticProps
。
404 页面只是一个包罗万象的 funnel
路由,当用户导航到以您的站点为基础 URL 时不存在的路径时,用户将被重定向到该路由。因此,它在初始构建时不依赖于服务器。这是不存在路径的回退,仅此而已。另一方面,500 页面处理应用程序中的内部错误,因此它 依赖 .html
和 .json
文件类型来查明错误的性质错误。
有趣的是,如果您在本地检查 .next
目录的内容,您会注意到所有使用 GetStaticProps
的页面都有静态生成的 .json
和 .html
文件.使用 GetStaticProps
和 revalidate
returned === Incremental Static Regeneration
或 ISR
的页面。 ISR
是 SSG
和 SSR
的理想混合体,具有后台功能扫描生产中传入的 changes/updates(您指定的数字是可能更新之间的时间量(以秒为单位) ).因此,带有 GetStaticProps
+ ISR
的页面会在 .next
目录中生成三种文件类型——.html
、.json
和 .js
。也就是说,使用 GetServerSideProps
或 GetInitialProps
的页面只会在 .next
目录中生成 .js
个文件。最后,纯Static
的页面,使用上述方法none,只生成了.html
个文件。
404 页面及其静态特性背后的想法是通过加快自定义 oops! that path doesn't exist
页面的呈现(或更正确的预呈现)来增强用户体验,以便用户可以 return尽快实际申请。
例如,我的 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;
有趣的是,因为我在 404.tsx
页面中使用 GetStaticProps
和 revalidate
作为 ISR
,.next
目录的内容反映了这一点404
(.js, .json, .html
) 所有三种文件类型都存在。如果您在自定义 _app.tsx
或 _app.js
文件中使用 getInitialProps
,则整个应用程序的自动静态优化(静态页面的预呈现)将被禁用。如果您好奇,请尝试一下,它应该会导致 404 页面在您的构建日志中旁边有一个 lambda。但是,由于您已经有 GetStaticProps
,它应该使用 GetInitialProps
app
页面引起的应用程序范围内的静态去优化
例如,在创建自定义 404.tsx
页面之前,我在 _app.tsx
中使用了 GetInitialProps
。我决定提取构建日志并拍摄随附的屏幕截图。
Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`.