老规矩,昨天写了关于 getServerSideProps
的内容,今天趁热写一下 getServerSideProps
相应的源码,看看 next.js getServerSideProps
是怎么实现的,还有什么从文档无法知晓的细节。
SSR 处理
我们先从 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 页面代码而不报错的,毕竟页面代码中很可能会存在依赖浏览器环境的代码,估计是做了一些类似于 runtime shim 之类的操作?此处先挖个坑,以后有空研究下。突然想起页面都是 SSR
了,初始化代码肯定都做过处理了