欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

next.js?getServerSideProps源碼解析

 更新時間:2022年10月11日 08:42:17   作者:嘿嘿Z  
這篇文章主要為大家介紹了next.js?getServerSideProps源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

SSR 處理

老規(guī)矩,昨天寫了關(guān)于 getServerSideProps 的內(nèi)容,今天趁熱寫一下 getServerSideProps 相應(yīng)的源碼,看看 next.js getServerSideProps 是怎么實現(xiàn)的,還有什么從文檔無法知曉的細節(jié)。

我們先從 SSR 時相關(guān)的 getServerSideProps 處理看起,源碼排查步驟上一步已經(jīng)有所介紹,本篇不再多說,在 SSR 時,next.js 會調(diào)用 doRender 來進行渲染,其中會再次調(diào)用 renderHTML,進過各種判斷和調(diào)用最終會進入 packages/next/server/render.tsx 中的 renderToHTML 進行處理。

// const SERVER_PROPS_ID = "__N_SSP";
if (getServerSideProps) {
    props[SERVER_PROPS_ID] = true;
}

next.js 會先將 props 中的 SERVER_PROPS_ID 設(shè)置為 true,用做標識。

try {
    data = await getServerSideProps({
        req: req as IncomingMessage & {
            cookies: NextApiRequestCookies;
        },
        res: resOrProxy,
        query,
        resolvedUrl: renderOpts.resolvedUrl as string,
        ...(pageIsDynamic ? { params: params as ParsedUrlQuery } : undefined),
        ...(previewData !== false ? { preview: true, previewData: previewData } : undefined),
        locales: renderOpts.locales,
        locale: renderOpts.locale,
        defaultLocale: renderOpts.defaultLocale
    });
    canAccessRes = false;
} catch (serverSidePropsError: any) {
    if (isError(serverSidePropsError) && serverSidePropsError.code === 'ENOENT') {
        delete serverSidePropsError.code;
    }
    throw serverSidePropsError;
}
if (data == null) {
    throw new Error(GSSP_NO_RETURNED_VALUE);
}
if ((data as any).props instanceof Promise) {
    deferredContent = true;
}
const invalidKeys = Object.keys(data).filter(key => key !== 'props' && key !== 'redirect' && key !== 'notFound');
if (invalidKeys.length) {
    throw new Error(invalidKeysMsg('getServerSideProps', invalidKeys));
}

注意這里的 getServerSideProps 是從外層傳進來了,因為涉及的代碼較多,就不貼了,主要是通過 packages/next/server/load-components 中的 loadComponents,將路由文件中的 getServerSideProps 通過從 require 后的頁面中取出。不過挺好奇他在 node 端是怎么 require 頁面代碼而不報錯的,畢竟頁面代碼中很可能會存在依賴瀏覽器環(huán)境的代碼,估計是做了一些類似于 runtime shim 之類的操作?此處先挖個坑,以后有空研究下。突然想起頁面都是 SSR 了,初始化代碼肯定都做過處理了 ??。

上面的代碼可以看出 SSR 的時候是直接調(diào)用 getServerSideProps 傳入 context 內(nèi)容,context 的內(nèi)容也一目了然。然后 next.js 會校驗返回值是否為空,或者是否包含非法參數(shù)等。

然后回去檢查 notFoundredirect 參數(shù),進行特殊處理。

if ('notFound' in data && data.notFound) {
    if (pathname === '/404') {
        throw new Error(`The /404 page can not return notFound in "getStaticProps", please remove it to continue!`);
    }
    (renderOpts as any).isNotFound = true;
    return null;
}
if ('redirect' in data && typeof data.redirect === 'object') {
    checkRedirectValues(data.redirect as Redirect, req, 'getServerSideProps');
    (data as any).props = {
        __N_REDIRECT: data.redirect.destination,
        __N_REDIRECT_STATUS: getRedirectStatus(data.redirect)
    };
    if (typeof data.redirect.basePath !== 'undefined') {
        (data as any).props.__N_REDIRECT_BASE_PATH = data.redirect.basePath;
    }
    (renderOpts as any).isRedirect = true;
}

此外從上面這段代碼還發(fā)現(xiàn)一個有意思的就是 props 是可以為 Promise 的:

if ((data as any).props instanceof Promise) {
    deferredContent = true;
}

返回 Promise 時,next.js 會在異常處理完畢后獲取值:

if (deferredContent) {
    (data as any).props = await(data as any).props;
}

最后 next.js 會將獲取到的 props 值放入到頂層的 props 中:

props.pageProps = Object.assign({}, props.pageProps, (data as any).props);
(renderOpts as any).pageData = props;

SSR 時,我們在頁面中看到的用于 hydrate__NEXT_DATA__ 中的 props 就是這個 props,可以再看一眼其中的數(shù)據(jù):

<script id="__NEXT_DATA__" type="application/json">
    {
        "props": {
            "pageProps": {
                "feature": {
                    "name": "xxxx",
                    "desc": "xxxx",
                    "tags": ["xxx"],
                    "id": "account-manage"
                }
            },
            "__N_SSP": true
        },
        "page": "/feature/[fid]",
        "query": { "fid": "account-manage" },
        "buildId": "development",
        "isFallback": false,
        "gssp": true,
        "scriptLoader": []
    }
</script>

可以看到 pageProps__N_SSP 都是上面放進去的。

動態(tài)加載處理

看完了 SSR 場景下,next.js 如何處理 getServerSideProps,我們再看下頁面為動態(tài)加載時的處理。

通過跳轉(zhuǎn)時發(fā)起請求的調(diào)用棧,我們很輕松就能找到在頁面為動態(tài)加載時,next.js 將會通過 packages/next/shared/lib/router.ts 中的 getRouteInfo 來獲取要跳轉(zhuǎn)的頁面信息,然后會通過 routeInfo__N_SSP 判定是否要去獲取數(shù)據(jù):

const shouldFetchData = routeInfo.__N_SSG || routeInfo.__N_SSP;
if (shouldFetchData) {
    const { json, cacheKey: _cacheKey } = data?.json
        ? data
        : await fetchNextData({
              dataHref: this.pageLoader.getDataHref({
                  href: formatWithValidation({ pathname, query }),
                  asPath: resolvedAs,
                  locale
              }),
              isServerRender: this.isSsr,
              parseJSON: true,
              inflightCache: this.sdc,
              persistCache: !isPreview,
              isPrefetch: false,
              unstable_skipClientCache
          });
    return {
        cacheKey: _cacheKey,
        props: json || {}
    };
}

然后通過 fetchNextData 來獲取數(shù)據(jù),而我們上文提到的 _next/data/development/{url}.json?{query} 這段 URL 就是由 formatWithValidation 構(gòu)建生成的。

而請求發(fā)送后服務(wù)端的處理就七繞八繞邏輯太深了,這里不一一列舉代碼,簡單說下:next.js 會通過 /_next/data/ 匹配請求判斷是否是數(shù)據(jù)請求,如果是數(shù)據(jù)請求將會一樣執(zhí)行 SSR代碼,然后可以理解為走的就是上面 SSR 初始化時的那套邏輯,只是最后會按照數(shù)據(jù)請求標識,將 props 抽離出來,放到響應(yīng)中中返回。

總結(jié)

getServerSideProps 相關(guān)的源碼還是有點繞的,其中應(yīng)該還少了一些其它場景的相關(guān)代碼,不過只看主場景應(yīng)該就是這些了。

以上就是next.js getServerSideProps源碼解析的詳細內(nèi)容,更多關(guān)于next.js getServerSideProps的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論