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

next.js?getServerSideProps源碼解析

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

SSR 處理

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

我們先從 SSR 時相關的 getServerSideProps 處理看起,源碼排查步驟上一步已經有所介紹,本篇不再多說,在 SSR 時,next.js 會調用 doRender 來進行渲染,其中會再次調用 renderHTML,進過各種判斷和調用最終會進入 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 設置為 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 的時候是直接調用 getServerSideProps 傳入 context 內容,context 的內容也一目了然。然后 next.js 會校驗返回值是否為空,或者是否包含非法參數等。

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

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,可以再看一眼其中的數據:

<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)加載時的處理。

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

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 來獲取數據,而我們上文提到的 _next/data/development/{url}.json?{query} 這段 URL 就是由 formatWithValidation 構建生成的。

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

總結

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

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

相關文章

最新評論