Next.js 在应该的时候没有将页面构建为 SSG

时间:2021-04-29 09:54:50

标签: javascript build next.js prismic.io

我试图理解为什么 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
            }
        }
    }
};

enter image description here

2 个答案:

答案 0 :(得分:4)

Current-Deployment-Details

Next.js 中的 404.tsx 或 404.js 页面的独特之处在于它不依赖于服务器并且始终是静态的——仅依赖于静态 html(无 json)在构建时 -- 即使在文件中使用 GetStaticProps

404 页面只是一个捕获所有 funnel 路由,当用户导航到您的网站不存在的路径作为基本 URL 时,用户会重定向到该路由。因此,它在初始构建时不依赖于服务器。这是不存在的路径的后备,没有别的。另一方面,500 页处理应用程序中的内部错误,因此它确实依赖 .html.json 文件类型来查明错误的性质。

有趣的是,如果您在本地检查 .next 目录的内容,您会注意到所有使用 GetStaticProps 的页面都静态生成了 .json.html 文件。使用 GetStaticPropsrevalidate 的页面返回 === Incremental Static RegenerationISRISRSSGSSR 的理想混合体,具有后台功能扫描生产中的传入更改/更新(您指定的数字是可能更新之间的时间量(以秒为单位))。因此,带有 GetStaticProps + ISR 的页面会在 .next 目录中生成三种文件类型——.html.json.js。也就是说,使用 GetServerSidePropsGetInitialProps 的页面在 .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 页面中将 revalidateISR 用于 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`.

404-static-deoptimization

答案 1 :(得分:0)

您的代码中的 404 页面是否缺少括号?

const response = await apolloClient.query({
    query: gql`
        query {
        }
    `
};

应该

const response = await apolloClient.query({
    query: gql`
        query {
        }
    `
});