最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

next.js?getServerSideProps源碼解析

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

SSR 處理

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

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

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

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

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 是從外層傳進(jìn)來了,因?yàn)樯婕暗拇a較多,就不貼了,主要是通過 packages/next/server/load-components 中的 loadComponents,將路由文件中的 getServerSideProps 通過從 require 后的頁面中取出。不過挺好奇他在 node 端是怎么 require 頁面代碼而不報(bào)錯(cuò)的,畢竟頁面代碼中很可能會存在依賴瀏覽器環(huán)境的代碼,估計(jì)是做了一些類似于 runtime shim 之類的操作?此處先挖個(gè)坑,以后有空研究下。突然想起頁面都是 SSR 了,初始化代碼肯定都做過處理了 ??。

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

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

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)一個(gè)有意思的就是 props 是可以為 Promise 的:

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

返回 Promise 時(shí),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 時(shí),我們在頁面中看到的用于 hydrate__NEXT_DATA__ 中的 props 就是這個(gè) 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 都是上面放進(jìn)去的。

動(dòng)態(tài)加載處理

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

通過跳轉(zhuǎn)時(shí)發(fā)起請求的調(diào)用棧,我們很輕松就能找到在頁面為動(dòng)態(tài)加載時(shí),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í)的那套邏輯,只是最后會按照數(shù)據(jù)請求標(biāo)識,將 props 抽離出來,放到響應(yīng)中中返回。

總結(jié)

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

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

相關(guān)文章

最新評論

手机| 信宜市| 军事| 长乐市| 浑源县| 漳州市| 胶南市| 新泰市| 青河县| 宁河县| 绥滨县| 安泽县| 禄丰县| 海城市| 贵州省| 巴彦淖尔市| 调兵山市| 大埔县| 昆山市| 泸水县| 遵化市| 濉溪县| 翁牛特旗| 绩溪县| 衡水市| 大渡口区| 宁安市| 忻州市| 庄河市| 威宁| 杨浦区| 日照市| 同德县| 客服| 山阳县| 斗六市| 沁源县| 天长市| 辉南县| 永安市| 昌宁县|