<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                服務端渲染(SSR)近兩年炒得很火熱,相信各位同學對這個名詞多少有所耳聞。本節我們將圍繞“是什么”(服務端渲染的運行機制)、“為什么”(服務端渲染解決了什么性能問題 )、“怎么做”(服務端渲染的應用實例與使用場景)這三個點,對服務端渲染進行探索。 服務端渲染是一個相對的概念,它的對立面是“客戶端渲染”。在運行機制解析這部分,我們會借力客戶端渲染的概念,來幫大家理解服務端渲染的工作方式。基于對工作方式的了解,再去深挖它的原理與優勢。 任何知識點都不是“一座孤島”,服務端渲染的實踐往往與當下流行的前端技術(譬如 Vue,React,Redux 等)緊密結合。本節下半場將以 React 和 Vue 下的服務端渲染實現為例,為大家呈現一個完整的 SSR 實現過程。 ## 服務端渲染的運行機制 相對于服務端渲染,同學們普遍對客戶端渲染接受度更高一些,所以我們先從大家喜聞樂見的客戶端渲染說起。 ### 客戶端渲染 客戶端渲染模式下,服務端會把渲染需要的靜態文件發送給客戶端,客戶端加載過來之后,自己在瀏覽器里跑一遍 JS,根據 JS 的運行結果,生成相應的 DOM。這種特性使得客戶端渲染的源代碼總是特別簡潔,往往是這個德行: ``` <!doctype html> <html> <head> <title>我是客戶端渲染的頁面</title> </head> <body> <div id='root'></div> <script src='index.js'></script> </body> </html> ``` 根節點下到底是什么內容呢?你不知道,我不知道,只有瀏覽器把 index.js 跑過一遍后才知道,這就是典型的客戶端渲染。 **頁面上呈現的內容,你在 html 源文件里里找不到**——這正是它的特點。 ### 服務端渲染 服務端渲染的模式下,當用戶第一次請求頁面時,由服務器把需要的組件或頁面渲染成 HTML 字符串,然后把它返回給客戶端。客戶端拿到手的,是可以直接渲染然后呈現給用戶的 HTML 內容,不需要為了生成 DOM 內容自己再去跑一遍 JS 代碼。 使用服務端渲染的網站,可以說是“所見即所得”,**頁面上呈現的內容,我們在 html 源文件里也能找到**。 比如知乎就是典型的服務端渲染案例: ![](https://user-gold-cdn.xitu.io/2018/9/26/166162c1cbad2c64?w=2736&h=582&f=png&s=351372) zhihu.com 返回的 HTML 文件已經是可以直接進行渲染的內容了。 ## 服務端渲染解決了什么性能問題 事實上,很多網站是出于效益的考慮才啟用服務端渲染,性能倒是在其次。 假設 A 網站頁面中有一個關鍵字叫“前端性能優化”,這個關鍵字是 JS 代碼跑過一遍后添加到 HTML 頁面中的。那么客戶端渲染模式下,我們在搜索引擎搜索這個關鍵字,是找不到 A 網站的——搜索引擎只會查找現成的內容,不會幫你跑 JS 代碼。A 網站的運營方見此情形,感到很頭大:搜索引擎搜不出來,用戶找不到我們,誰還會用我的網站呢?為了把“現成的內容”拿給搜索引擎看,A 網站不得不啟用服務端渲染。 但性能在其次,不代表性能不重要。服務端渲染解決了一個非常關鍵的性能問題——首屏加載速度過慢。在客戶端渲染模式下,我們除了加載 HTML,還要等渲染所需的這部分 JS 加載完,之后還得把這部分 JS 在瀏覽器上再跑一遍。這一切都是發生在用戶點擊了我們的鏈接之后的事情,在這個過程結束之前,用戶始終見不到我們網頁的廬山真面目,也就是說用戶一直在等!相比之下,服務端渲染模式下,服務器給到客戶端的已經是一個直接可以拿來呈現給用戶的網頁,中間環節早在服務端就幫我們做掉了,用戶豈不“美滋滋”? ## 服務端渲染的應用實例 下面我們先來看一下在一個 React 項目里,服務端渲染是怎么實現的。本例中,我們使用 Express 搭建后端服務。 項目中有一個叫做 VDom 的 React 組件,它的內容如下。 VDom.js: ``` import React from 'react' const VDom = () => { return <div>我是一個被渲染為真實DOM的虛擬DOM</div> } export default VDom ``` 在服務端的入口文件中,我引入這個組件,對它進行渲染: ``` import express from 'express' import React from 'react' import { renderToString } from 'react-dom/server' import VDom from './VDom' // 創建一個express應用 const app = express() // renderToString 是把虛擬DOM轉化為真實DOM的關鍵方法 const RDom = renderToString(<VDom />) // 編寫HTML模板,插入轉化后的真實DOM內容 const Page = ` <html> <head> <title>test</title> </head> <body> <span>服務端渲染出了真實DOM: </span> ${RDom} </body> </html> ` // 配置HTML內容對應的路由 app.get('/index', function(req, res) { res.send(Page) }) // 配置端口號 const server = app.listen(8000) ``` 根據我們的路由配置,當我訪問 [http://localhost:8000/index](http://localhost:8000/index) 時,就可以呈現出服務端渲染的結果了: ![](https://user-gold-cdn.xitu.io/2018/9/26/16615e831fa4c113?w=1502&h=408&f=png&s=129026) 我們可以看到,VDom 組件已經被 renderToString 轉化為了一個內容為`<div data-reactroot="">我是一個被渲染為真實DOM的虛擬DOM</div>`的字符串,這個字符串被插入 HTML 代碼,成為了真實 DOM 樹的一部分。 那么 Vue 是如何實現服務端渲染的呢? 其實是一個套路,我這里基于 [Vue SSR 指南](https://ssr.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B8%B2%E6%9F%93-ssr-%EF%BC%9F) 中官方給出的例子為大家講解 Vue 中的實現思路(思路見注釋)。 該示例直接將 Vue 實例整合進了服務端的入口文件中: ``` const Vue = require('vue') // 創建一個express應用 const server = require('express')() // 提取出renderer實例 const renderer = require('vue-server-renderer').createRenderer() server.get('*', (req, res) => { // 編寫Vue實例(虛擬DOM節點) const app = new Vue({ data: { url: req.url }, // 編寫模板HTML的內容 template: `<div>訪問的 URL 是: {{ url }}</div>` }) // renderToString 是把Vue實例轉化為真實DOM的關鍵方法 renderer.renderToString(app, (err, html) => { if (err) { res.status(500).end('Internal Server Error') return } // 把渲染出來的真實DOM字符串插入HTML模板中 res.end(` <!DOCTYPE html> <html lang="en"> <head><title>Hello</title></head> <body>${html}</body> </html> `) }) }) server.listen(8080) ``` 大家對比一下 React 項目中的注釋內容,是不是發現這兩段代碼從本質上來說區別不大呢? 以上兩個小??,為大家演示了基本的服務端渲染實現流程。 實際項目比這些復雜很多,但萬變不離其宗。強調的只有兩點:一是這個 renderToString() 方法;二是把轉化結果“塞”進模板里的這一步。這兩個操作是服務端渲染的靈魂操作。在虛擬 DOM“橫行”的當下,服務端渲染不再是早年 JSP 里簡單粗暴的字符串拼接過程,它還要求這一端要具備將虛擬 DOM 轉化為真實 DOM 的能力。與其說是“把 JS 在服務器上先跑一遍”,不如說是“把 Vue、React 等框架代碼先在 Node 上跑一遍”。 ## 服務端渲染的應用場景 打眼一看,這個服務端渲染給瀏覽器省了這么多事兒,性能肯定是質的飛躍啊!喜聞樂見!但是大家打開自己經常訪問的那些網頁看一看,會發現仍然有許多網站壓根兒不用服務端渲染——看來這個東西也不是萬能的。 根據我們前面的描述,不難看出,服務端渲染本質上是**本該瀏覽器做的事情,分擔給服務器去做**。這樣當資源抵達瀏覽器時,它呈現的速度就快了。乍一看好像很合理:瀏覽器性能畢竟有限,服務器多牛逼!能者多勞,就該讓服務器多干點活! 但仔細想想,在這個網民遍地的時代,幾乎有多少個用戶就有多少臺瀏覽器。用戶擁有的瀏覽器總量多到數不清,那么一個公司的服務器又有多少臺呢?我們把這么多臺瀏覽器的渲染壓力集中起來,分散給相比之下數量并不多的服務器,服務器肯定是承受不住的。 這樣分析下來,服務端渲染也并非萬全之策。在實踐中,我一般會建議大家先忘記服務端渲染這個事情——服務器稀少而寶貴,但首屏渲染體驗和 SEO 的優化方案卻很多——我們最好先把能用的低成本“大招”都用完。除非網頁對性能要求太高了,以至于所有的招式都用完了,性能表現還是不盡人意,這時候我們就可以考慮向老板多申請幾臺服務器,把服務端渲染搞起來了~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看