亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Next.js源碼解析【服務(wù)端渲染過(guò)程,以及_document、_app、pages這三者調(diào)用關(guān)系】

jeffrey_up / 2690人閱讀

摘要:補(bǔ)充上文中出現(xiàn)的部分函數(shù),直接截取自源碼,都相對(duì)簡(jiǎn)單,可以作為參考很多參數(shù),太長(zhǎng)省略

入口

這是一個(gè)基礎(chǔ)demo,由開(kāi)發(fā)者自己提供server,用于渲染

const Koa = require("koa")
const Router = require("koa-router")
const next = require("next")
// 創(chuàng)建實(shí)例
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)
})

在自定義服務(wù)端中通過(guò)const app = next()創(chuàng)建實(shí)例并使用app.render(req, res)方法進(jìn)行渲染

所以直接從app.render這個(gè)渲染入口開(kāi)始著手

了解框架邏輯唯一的方式就是看源碼,由于源碼過(guò)于細(xì)節(jié),下面我會(huì)簡(jiǎn)化涉及到的代碼,僅保留主要邏輯,附帶具體地址,有興趣深入的同學(xué)可以看看
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內(nèi)的renderToHTML
    return renderToHTML(req, res)
}

可以看到上面都是簡(jiǎn)單的調(diào)用關(guān)系,雖然刪除了大部分代碼,但我們只需要知道,最終它調(diào)用了render.tsx內(nèi)的renderToHTML

這是一個(gè)相當(dāng)長(zhǎng)的函數(shù),也就是本篇文章的主要內(nèi)容,通過(guò)renderToHTML能夠了解到大部分內(nèi)容,和上面相同,刪除了大部分邏輯,僅保留核心代碼

renderToHTML
// next-server/server/render.tsx
function renderToHTML(req, res) {
// 參考下文#補(bǔ)充 loadGetInitialProps,非常簡(jiǎn)單的函數(shù),就是調(diào)用了_app.getInitialProps
// _app.getInitialProps函數(shù)內(nèi)部會(huì)先調(diào)用pages.Component的getInitialProps
// 也就是在這里,我們編寫的組件內(nèi)的getInitialProps同樣會(huì)被調(diào)用,獲取部分初始數(shù)據(jù)
  let props = await loadGetInitialProps(App, { Component, router, ctx });
  
  // 定義渲染函數(shù),返回html和head
  const renderPage = () => {
    // 參考下文#補(bǔ)充 render
    return render(
      renderToStaticMarkup,
      //渲染_app,以及其內(nèi)部的pages.Component也就是我們編寫的代碼,詳情參考next/pages/_app.tsx
      
    );
  };
  
// _document.getInitialProps會(huì)調(diào)用renderPage,渲染_app也就是我們的正常開(kāi)發(fā)時(shí)編寫的組件代碼,詳情參考next/pages/_app.tsx
  const docProps = await loadGetInitialProps(Document, { ...ctx, renderPage });
  
// 參考下文#補(bǔ)充 renderDocument
  let html = renderDocument(Document, {
    props,
    docProps,
  });
  return html;
}
小結(jié)
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

對(duì)應(yīng)

req=>
    _app.getInitialProps()
        Component.getInitialProps()
    _document.getInitialProps()
        _app.render()
            Component.render()
    _document.render()
<=res

這篇文章簡(jiǎn)要描述next服務(wù)端的渲染過(guò)程,從中我們也能清楚_document、_app、以及pages內(nèi)自己編寫的組件之間的關(guān)系...

要是還沒(méi)明白,請(qǐng)重新閱讀一遍renderToHTML函數(shù)內(nèi)的注釋內(nèi)容

需要注意的一些點(diǎn),隨緣補(bǔ)充

_document只在服務(wù)端被執(zhí)行,瀏覽器端是不會(huì)執(zhí)行的

react提供的renderToString函數(shù)只產(chǎn)出html,也就是純粹的string,所有數(shù)據(jù)必須在調(diào)用renderToString之前注入

在瀏覽器端渲染時(shí),存在isInitialRender用于標(biāo)示是否第一次渲染,如果是第一次渲染,會(huì)調(diào)用ReactDOM.hydrate(reactEl, domEl)來(lái)執(zhí)行綁定事件,所以部分生命周期(componentWillMount之后)以及事件會(huì)在瀏覽器端執(zhí)行。

補(bǔ)充

上文中出現(xiàn)的部分函數(shù),直接截取自源碼,都相對(duì)簡(jiǎn)單,可以作為參考

render
function render(
    renderElementToString: (element: React.ReactElement) => 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 }
  }
loadGetInitialProps
export async function loadGetInitialProps(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
    }
renderDocument
function renderDocument(
    Document: DocumentType,
    {...很多參數(shù),太長(zhǎng)省略}
  ): string {
    return (
      "" +
      renderToStaticMarkup(
        
          
        ,
      )
    )
  }

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109451.html

相關(guān)文章

  • Nextjs中文文檔

    摘要:中文站點(diǎn)中文站當(dāng)前翻譯版本為。注意將不能使用在子組件中。只能使用在頁(yè)面中。替換路由組件默認(rèn)將新推入路由棧中。以防服務(wù)端渲染發(fā)生錯(cuò)誤,建議事件寫在生命周期里。禁止文件路由默認(rèn)情況,將會(huì)把下的所有文件匹配路由如渲染為如果你的項(xiàng)目使用 Next.js 是一個(gè)輕量級(jí)的 React 服務(wù)端渲染應(yīng)用框架。 Next.js中文站點(diǎn) http://nextjs.frontendx.cn Next.j...

    luckyw 評(píng)論0 收藏0
  • 基于 Webpack 4 多入口生成模板用于服務(wù)渲染的方案及實(shí)戰(zhàn)

    摘要:原作者原鏈接基于多入口生成模板用于服務(wù)端渲染的方案及實(shí)戰(zhàn)法律聲明警告本作品遵循署名非商業(yè)性使用禁止演繹未本地化版本協(xié)議發(fā)布。這是什么背景現(xiàn)代化的前端項(xiàng)目中很多都使用了客戶端渲染的單頁(yè)面應(yīng)用。 原作者:@LinuxerPHL原鏈接:基于 Webpack 4 多入口生成模板用于服務(wù)端渲染的方案及實(shí)戰(zhàn) 法律聲明 警告:本作品遵循 署名-非商業(yè)性使用-禁止演繹3.0 未本地化版本(CC BY-...

    big_cat 評(píng)論0 收藏0
  • 基于 Webpack 4 多入口生成模板用于服務(wù)渲染的方案及實(shí)戰(zhàn)

    摘要:原作者原博文地址基于多入口生成模板用于服務(wù)端渲染的方案及實(shí)戰(zhàn)法律聲明警告本作品遵循署名非商業(yè)性使用禁止演繹未本地化版本協(xié)議發(fā)布。這是什么背景現(xiàn)代化的前端項(xiàng)目中很多都使用了客戶端渲染的單頁(yè)面應(yīng)用。 原作者:@LinuxerPHL原博文地址: 基于 Webpack 4 多入口生成模板用于服務(wù)端渲染的方案及實(shí)戰(zhàn) 法律聲明 警告:本作品遵循 署名-非商業(yè)性使用-禁止演繹3.0 未本地化版本(...

    Lavender 評(píng)論0 收藏0
  • 從零開(kāi)始,揭秘React服務(wù)渲染核心技術(shù)

    摘要:不過(guò)這時(shí)的控制臺(tái)會(huì)拋出這樣一則警告提醒我們?cè)诜?wù)端渲染時(shí)用來(lái)取代,并警告我們?cè)跁r(shí)將不能用去混合服務(wù)端渲染出來(lái)的標(biāo)簽。綜上所述,服務(wù)端和客戶端都是需要路由體現(xiàn)的。我們畫一下重點(diǎn),意思很明確,就是為了服務(wù)端渲染而打造的。 拋磚引玉 在早幾年前,jquery算是一個(gè)前端工程師必備的技能。當(dāng)時(shí)很多公司采用的是java結(jié)合像velocity或者freemarker這種模板引擎的開(kāi)發(fā)模式,頁(yè)面渲染...

    googollee 評(píng)論0 收藏0
  • webpack實(shí)戰(zhàn)

    摘要:和類似的預(yù)處理器還有等。的用處非常多,包括給自動(dòng)加前綴使用下一代語(yǔ)法等,目前越來(lái)越多的人開(kāi)始用它,它很可能會(huì)成為預(yù)處理器的最終贏家。 webpack實(shí)戰(zhàn) 查看所有文檔頁(yè)面:全棧開(kāi)發(fā),獲取更多信息??祚R加鞭,加班加點(diǎn),終于把這個(gè)文檔整理出來(lái)了,順便深入地學(xué)習(xí)一番,鞏固知識(shí),就是太累人,影響睡眠時(shí)間和質(zhì)量。極客就是想要把事情做到極致,開(kāi)始了就必須到達(dá)終點(diǎn)。 原文鏈接:webpack實(shí)戰(zhàn),原...

    cyrils 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<