摘要:補充上文中出現(xiàn)的部分函數(shù),直接截取自源碼,都相對簡單,可以作為參考很多參數(shù),太長省略
入口
這是一個基礎demo,由開發(fā)者自己提供server,用于渲染
const Koa = require("koa") const Router = require("koa-router") const next = require("next") // 創(chuàng)建實例 const app = next({ dev, conf, dir: "./src" }) app.prepare().then(() => { const server = new Koa() const router = new Router() router.get("/", async ctx => { // 渲染 await app.render(ctx.req, ctx.res) ctx.respond = false }) server.listen(port) })
在自定義服務端中通過const app = next()創(chuàng)建實例并使用app.render(req, res)方法進行渲染
所以直接從app.render這個渲染入口開始著手
了解框架邏輯唯一的方式就是看源碼,由于源碼過于細節(jié),下面我會簡化涉及到的代碼,僅保留主要邏輯,附帶具體地址,有興趣深入的同學可以看看app.render
next-server/server/next-server.ts
import { renderToHTML } from "./render.tsx" // app.render入口函數(shù) this.render(req, res){ const html = await this.renderToHTML(req, res) return this.sendHTML(req, res, html) } this.renderToHTML(req, res){ const html = await this.renderToHTMLWithComponents(req, res) return html } this.renderToHTMLWithComponents(req, res) { // render內的renderToHTML return renderToHTML(req, res) }
可以看到上面都是簡單的調用關系,雖然刪除了大部分代碼,但我們只需要知道,最終它調用了render.tsx內的renderToHTML
這是一個相當長的函數(shù),也就是本篇文章的主要內容,通過renderToHTML能夠了解到大部分內容,和上面相同,刪除了大部分邏輯,僅保留核心代碼
renderToHTML// next-server/server/render.tsx function renderToHTML(req, res) { // 參考下文#補充 loadGetInitialProps,非常簡單的函數(shù),就是調用了_app.getInitialProps // _app.getInitialProps函數(shù)內部會先調用pages.Component的getInitialProps // 也就是在這里,我們編寫的組件內的getInitialProps同樣會被調用,獲取部分初始數(shù)據(jù) let props = await loadGetInitialProps(App, { Component, router, ctx }); // 定義渲染函數(shù),返回html和head const renderPage = () => { // 參考下文#補充 render return render( renderToStaticMarkup, //渲染_app,以及其內部的pages.Component也就是我們編寫的代碼,詳情參考next/pages/_app.tsx小結); }; // _document.getInitialProps會調用renderPage,渲染_app也就是我們的正常開發(fā)時編寫的組件代碼,詳情參考next/pages/_app.tsx const docProps = await loadGetInitialProps(Document, { ...ctx, renderPage }); // 參考下文#補充 renderDocument let html = renderDocument(Document, { props, docProps, }); return html; }
req=> render(req, res) renderToHTML(req, res) renderToHTMLWithComponents(req, res) renderToHTML(req,res) _app.initialProps = loadGetInitialProps(App, { Component, router, ctx }) _document.initialProps = loadGetInitialProps(Document, { ...ctx, renderPage }) renderDocument(Document, _app.initialProps, _document.initialProps) <=res
對應
req=> _app.getInitialProps() Component.getInitialProps() _document.getInitialProps() _app.render() Component.render() _document.render() <=res
這篇文章簡要描述next服務端的渲染過程,從中我們也能清楚_document、_app、以及pages內自己編寫的組件之間的關系...
要是還沒明白,請重新閱讀一遍renderToHTML函數(shù)內的注釋內容
需要注意的一些點,隨緣補充
_document只在服務端被執(zhí)行,瀏覽器端是不會執(zhí)行的
react提供的renderToString函數(shù)只產(chǎn)出html,也就是純粹的string,所有數(shù)據(jù)必須在調用renderToString之前注入
在瀏覽器端渲染時,存在isInitialRender用于標示是否第一次渲染,如果是第一次渲染,會調用ReactDOM.hydrate(reactEl, domEl)來執(zhí)行綁定事件,所以部分生命周期(componentWillMount之后)以及事件會在瀏覽器端執(zhí)行。
補充上文中出現(xiàn)的部分函數(shù),直接截取自源碼,都相對簡單,可以作為參考
renderfunction render( renderElementToString: (element: React.ReactElementloadGetInitialProps) => string, element: React.ReactElement , ampMode: any, ): { html: string; head: React.ReactElement[] } { let html let head try { html = renderElementToString(element) } finally { head = Head.rewind() || defaultHead(undefined, isAmp(ampMode)) } return { html, head } }
export async function loadGetInitialPropsrenderDocument(Component: NextComponentType , ctx: C): Promise { if (process.env.NODE_ENV !== "production") { if (Component.prototype && Component.prototype.getInitialProps) { const message = `"${getDisplayName(Component)}.getInitialProps()" is defined as an instance method - visit https://err.sh/zeit/next.js/get-initial-props-as-an-instance-method for more information.` throw new Error(message) } } // when called from _app `ctx` is nested in `ctx` const res = ctx.res || (ctx.ctx && ctx.ctx.res) if (!Component.getInitialProps) { return null } const props = await Component.getInitialProps(ctx) if (res && isResSent(res)) { return props }
function renderDocument( Document: DocumentType, {...很多參數(shù),太長省略} ): string { return ( "" + renderToStaticMarkup(, ) ) }
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/109451.html
摘要:中文站點中文站當前翻譯版本為。注意將不能使用在子組件中。只能使用在頁面中。替換路由組件默認將新推入路由棧中。以防服務端渲染發(fā)生錯誤,建議事件寫在生命周期里。禁止文件路由默認情況,將會把下的所有文件匹配路由如渲染為如果你的項目使用 Next.js 是一個輕量級的 React 服務端渲染應用框架。 Next.js中文站點 http://nextjs.frontendx.cn Next.j...
摘要:原作者原鏈接基于多入口生成模板用于服務端渲染的方案及實戰(zhàn)法律聲明警告本作品遵循署名非商業(yè)性使用禁止演繹未本地化版本協(xié)議發(fā)布。這是什么背景現(xiàn)代化的前端項目中很多都使用了客戶端渲染的單頁面應用。 原作者:@LinuxerPHL原鏈接:基于 Webpack 4 多入口生成模板用于服務端渲染的方案及實戰(zhàn) 法律聲明 警告:本作品遵循 署名-非商業(yè)性使用-禁止演繹3.0 未本地化版本(CC BY-...
摘要:原作者原博文地址基于多入口生成模板用于服務端渲染的方案及實戰(zhàn)法律聲明警告本作品遵循署名非商業(yè)性使用禁止演繹未本地化版本協(xié)議發(fā)布。這是什么背景現(xiàn)代化的前端項目中很多都使用了客戶端渲染的單頁面應用。 原作者:@LinuxerPHL原博文地址: 基于 Webpack 4 多入口生成模板用于服務端渲染的方案及實戰(zhàn) 法律聲明 警告:本作品遵循 署名-非商業(yè)性使用-禁止演繹3.0 未本地化版本(...
摘要:不過這時的控制臺會拋出這樣一則警告提醒我們在服務端渲染時用來取代,并警告我們在時將不能用去混合服務端渲染出來的標簽。綜上所述,服務端和客戶端都是需要路由體現(xiàn)的。我們畫一下重點,意思很明確,就是為了服務端渲染而打造的。 拋磚引玉 在早幾年前,jquery算是一個前端工程師必備的技能。當時很多公司采用的是java結合像velocity或者freemarker這種模板引擎的開發(fā)模式,頁面渲染...
摘要:和類似的預處理器還有等。的用處非常多,包括給自動加前綴使用下一代語法等,目前越來越多的人開始用它,它很可能會成為預處理器的最終贏家。 webpack實戰(zhàn) 查看所有文檔頁面:全棧開發(fā),獲取更多信息??祚R加鞭,加班加點,終于把這個文檔整理出來了,順便深入地學習一番,鞏固知識,就是太累人,影響睡眠時間和質量。極客就是想要把事情做到極致,開始了就必須到達終點。 原文鏈接:webpack實戰(zhàn),原...
閱讀 1322·2023-04-26 03:05
閱讀 778·2021-10-19 11:43
閱讀 3227·2021-09-26 09:55
閱讀 835·2019-08-30 15:56
閱讀 991·2019-08-30 15:44
閱讀 1246·2019-08-30 15:44
閱讀 2726·2019-08-30 14:23
閱讀 3245·2019-08-30 13:13