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

詳解React 在服務(wù)端渲染的實現(xiàn)

 更新時間:2017年11月16日 09:21:20   作者:牧云云  
這篇文章主要介紹了詳解React 在服務(wù)端渲染的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

React是最受歡迎的客戶端 JavaScript 框架,但你知道嗎(可以試試),你可以使用 React 在服務(wù)器端進(jìn)行渲染?

假設(shè)你已經(jīng)在客戶端使用 React 構(gòu)建了一個事件列表 app。該應(yīng)用程序使用了您最喜歡的服務(wù)器端工具構(gòu)建的API。幾周后,用戶告訴您,他們的頁面沒有顯示在 Google 上,發(fā)布到 Facebook 時也顯示不出來。 這些問題似乎是可以解決的,對吧?

您會發(fā)現(xiàn),要解決這個問題,需要在初始加載時從服務(wù)器渲染 React 頁面,以便來自搜索引擎和社交媒體網(wǎng)站的爬蟲工具可以讀取您的標(biāo)記。有證據(jù)表明,Google 有時會執(zhí)行 javascript 程序并且對生成的內(nèi)容進(jìn)行索引,但并不總是的。因此,如果您希望確保與其他服​​務(wù)(如Facebook,Twitter)有良好的SEO兼容性,那么始終建議使用服務(wù)器端渲染。

在本教程中,我們將逐步介紹服務(wù)器端的呈現(xiàn)示例。包括圍繞與API交流的React應(yīng)用程序的共同路障。
 在本教程中,我們將逐步向您介紹服務(wù)器端的渲染示例。包括圍繞著 APIS 交流一些在服務(wù)端渲染 React 應(yīng)用程序的共同障礙。

服務(wù)端渲染的優(yōu)勢

可能您的團(tuán)隊談?wù)摰椒?wù)端渲染的好處是首先會想到 SEO,但這并不是唯一的潛在好處。

更大的好處如下:服務(wù)器端渲染能更快地顯示頁面。使用服務(wù)器端渲染,您的服務(wù)器對瀏覽器進(jìn)行響應(yīng)是在您的 HTML 頁面可以渲染的時候,因此瀏覽器可以不用等待所有的 JavaScript 被下載和執(zhí)行就可以開始渲染。當(dāng)瀏覽器下載并執(zhí)行頁面所需的 JavaScript 和其他資源時,不會出現(xiàn) “白屏” 現(xiàn)象,而 “白屏” 這是在完全有客戶端呈現(xiàn)的 React 網(wǎng)站中可能發(fā)生的情況。

入門

接下來讓我們來看看如何將服務(wù)器端渲染添加到一個基本的客戶端渲染的使用Babel和Webpack的React應(yīng)用程序中。我們的應(yīng)用程序?qū)⒃黾訌牡谌?API 獲取數(shù)據(jù)的復(fù)雜性。我們在GitHub上提供了相關(guān)代碼,您可以在其中看到完整的示例。

提供的代碼中只有一個 React 組件,`hello.js`,這個文件將向 ButterCMS 發(fā)出異步請求,并渲染返回的 JSON 列表的博文。ButterCMS 是一個基于API的博客引擎,可供個人使用,因此它非常適合測試現(xiàn)實生活中的用例。啟動代碼中連接著一個 API token,如果你想使用你自己的 API token 可以使用你的 GitHub 賬號登入 ButterCMS。

import React from 'react';
import Butter from 'buttercms'

const butter = Butter('b60a008584313ed21803780bc9208557b3b49fbb');

var Hello = React.createClass({
 getInitialState: function() {
  return {loaded: false};
 },
 componentWillMount: function() {
  butter.post.list().then((resp) => {
   this.setState({
    loaded: true,
    resp: resp.data
   })
  });
 },
 render: function() {
  if (this.state.loaded) {
   return (
    <div>
     {this.state.resp.data.map((post) => {
      return (
       <div key={post.slug}>{post.title}</div>
      )
     })}
    </div>
   );
  } else {
   return <div>Loading...</div>;
  }
 }
});

export default Hello;

啟動器代碼中包含以下內(nèi)容:

  1. package.json - 依賴項
  2. Webpack 和 Babel 配置
  3. index.html - app 的 HTML 文件
  4. index.js - 加載 React 并渲染 Hello 組件

要使應(yīng)用運行,請先克隆資源庫:

git clone ...
cd ..

安裝依賴:

npm install

然后啟動服務(wù)器:

npm run start

瀏覽器輸入 http://localhost:8000 可以看到這個 app: (這里譯者進(jìn)行補充,package.json 里的 start 命令改為如下:"start": webpack-dev-server --watch)

如果您查看渲染頁面的源代碼,您將看到發(fā)送到瀏覽器的標(biāo)記只是一個到 JavaScript 文件的鏈接。這意味著頁面的內(nèi)容不能保證被搜索引擎和社交媒體平臺抓取:

增加服務(wù)器端渲染

接下來,我們將實現(xiàn)服務(wù)器端渲染,以便將完全生成的HTML發(fā)送到瀏覽器。如果要同時查看所有更改,請查看GitHub上的差異。

To get started, we'll install Express, a Node.js server side application framework:

開始前,讓我們安裝 Express,一個 Node.js 的服務(wù)器端應(yīng)用程序框架:

npm install express --save

我們要創(chuàng)建一個渲染我們的 React 組件的服務(wù)器:

import express from 'express';
import fs from 'fs';
import path from 'path';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Hello from './Hello.js';

function handleRender(req, res) {
 // 把 Hello 組件渲染成 HTML 字符串
 const html = ReactDOMServer.renderToString(<Hello />);

 // 加載 index.html 的內(nèi)容
 fs.readFile('./index.html', 'utf8', function (err, data) {
  if (err) throw err;

  // 把渲染后的 React HTML 插入到 div 中
  const document = data.replace(/<div id="app"><\/div>/, `<div id="app">${html}</div>`);

  // 把響應(yīng)傳回給客戶端
  res.send(document);
 });
}

const app = express();

// 服務(wù)器使用 static 中間件構(gòu)建 build 路徑
app.use('/build', express.static(path.join(__dirname, 'build')));

// 使用我們的 handleRender 中間件處理服務(wù)端請求
app.get('*', handleRender);

// 啟動服務(wù)器
app.listen(3000);

讓我們分解下程序看看發(fā)生了什么事情...

handleRender 函數(shù)處理所有請求。在文件頂部導(dǎo)入的ReactDOMServer 類提供了將 React 節(jié)點渲染成其初始 HTML 的 renderToString() 方法

ReactDOMServer.renderToString(<Hello />);

這將返回 Hello 組件的 HTML ,我們將其注入到 index.html 的 HTML 中,從而生成服務(wù)器上頁面的完整 HTML 。

const document = data.replace(/<div id="app"><\/div>/,`<div id="app">${html}</div>`);

To start the server, update the start script in package.json and then run npm run start:

要啟動服務(wù)器,請更新 `package.json` 中的起始腳本,然后運行 npm run start :

"scripts": {
 "start": "webpack && babel-node server.js"
},

瀏覽 http://localhost:3000 查看應(yīng)用程序。瞧!您的頁面現(xiàn)在正在從服務(wù)器渲染出來了。但是有個問題,如果您在瀏覽器中查看頁面源碼,您會注意到博客文章仍未包含在回復(fù)中。這是怎么回事?如果我們在Chrome中打開網(wǎng)絡(luò)標(biāo)簽,我們會看到客戶端上發(fā)生API請求。

雖然我們在服務(wù)器上渲染了 React 組件,但是 API 請求在 componentWillMount 中異步生成,并且組件在請求完成之前渲染。所以即使我們已經(jīng)在服務(wù)器上完成渲染,但我們只是完成了部分。事實上,React repo 有一個 issue,超過 100 條評論討論了這個問題和各種解決方法。

在渲染之前獲取數(shù)據(jù)

要解決這個問題,我們需要在渲染 Hello 組件之前確保 API 請求完成。這意味著要使 API 請求跳出 React 的組件渲染循環(huán),并在渲染組件之前獲取數(shù)據(jù)。我們將逐步介紹這一步,但您可以在GitHub上查看完整的差異。

To move data fetching before rendering, we'll install react-transmit:

要在渲染之前獲取數(shù)據(jù),我們需安裝 react-transmit

npm install react-transmit --save

React Transmit 給了我們優(yōu)雅的包裝器組件(通常稱為“高階組件”),用于獲取在客戶端和服務(wù)器上工作的數(shù)據(jù)。

這是我們使用 react-transmit 后的組件的代碼:

import React from 'react';
import Butter from 'buttercms'
import Transmit from 'react-transmit';

const butter = Butter('b60a008584313ed21803780bc9208557b3b49fbb');

var Hello = React.createClass({
 render: function() {
  if (this.props.posts) {
   return (
    <div>
     {this.props.posts.data.map((post) => {
      return (
       <div key={post.slug}>{post.title}</div>
      )
     })}
    </div>
   );
  } else {
   return <div>Loading...</div>;
  }
 }
});

export default Transmit.createContainer(Hello, {
 // 必須設(shè)定 initiallVariables 和 ftagments ,否則渲染時會報錯
 initialVariables: {},
 // 定義的方法名將成為 Transmit props 的名稱
 fragments: {
  posts() {
   return butter.post.list().then((resp) => resp.data);
  }
 }
});

我們已經(jīng)使用 Transmit.createContainer 將我們的組件包裝在一個高級組件中,該組件可以用來獲取數(shù)據(jù)。我們在 React 組件中刪除了生命周期方法,因為無需兩次獲取數(shù)據(jù)。同時我們把 render 方法中的 state 替換成 props,因為 React Transmit 將數(shù)據(jù)作為 props 傳遞給組件。

為了確保服務(wù)器在渲染之前獲取數(shù)據(jù),我們導(dǎo)入 Transmit 并使用 Transmit.renderToString 而不是 ReactDOM.renderToString 方法

import express from 'express';
import fs from 'fs';
import path from 'path';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Hello from './Hello.js';
import Transmit from 'react-transmit';

function handleRender(req, res) {
 Transmit.renderToString(Hello).then(({reactString, reactData}) => {
  fs.readFile('./index.html', 'utf8', function (err, data) {
   if (err) throw err;

   const document = data.replace(/<div id="app"><\/div>/, `<div id="app">${reactString}</div>`);
   const output = Transmit.injectIntoMarkup(document, reactData, ['/build/client.js']);

   res.send(document);
  });
 });
}

const app = express();

// 服務(wù)器使用 static 中間件構(gòu)建 build 路徑
app.use('/build', express.static(path.join(__dirname, 'build')));

// 使用我們的 handleRender 中間件處理服務(wù)端請求
app.get('*', handleRender);

// 啟動服務(wù)器
app.listen(3000);

重新啟動服務(wù)器瀏覽到 http://localhost:3000。查看頁面源代碼,您將看到該頁面現(xiàn)在完全呈現(xiàn)在服務(wù)器上!

更進(jìn)一步

我們做到了!在服務(wù)器上使用 React 可能很棘手,尤其是從 API 獲取數(shù)據(jù)時。幸運的是,React社區(qū)正在蓬勃發(fā)展,并創(chuàng)造了許多有用的工具。如果您對構(gòu)建在客戶端和服務(wù)器上渲染的大型 React 應(yīng)用程序的框架感興趣,請查看 Walmart Labs 的 Electrode Next.js?;蛘呷绻?Ruby 中渲染 React ,請查看 AirBnB 的 Hypernova 。

 原文地址:https://css-tricks.com/server-side-react-rendering/

 原文作者:Roger Jin

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • react+antd.3x實現(xiàn)ip輸入框

    react+antd.3x實現(xiàn)ip輸入框

    這篇文章主要為大家詳細(xì)介紹了react+antd.3x實現(xiàn)ip輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • React和Vue組件更新的實現(xiàn)及區(qū)別

    React和Vue組件更新的實現(xiàn)及區(qū)別

    React 和 Vue 都是當(dāng)今最流行的前端框架,它們都實現(xiàn)了組件化開發(fā)模式,本文將從React和Vue的組件更新原理入手,剖析兩者虛擬DOM difer算法的異同點,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • React手寫tab切換問題

    React手寫tab切換問題

    今天介紹下React手寫tab切換問題,代碼部分包括父文件,子文件及子文件tab樣式,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2021-11-11
  • React 自動聚焦字段使用詳解

    React 自動聚焦字段使用詳解

    這篇文章主要為大家介紹了React 自動聚焦字段使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 嘗試自己動手用react來寫一個分頁組件(小結(jié))

    嘗試自己動手用react來寫一個分頁組件(小結(jié))

    本篇文章主要介紹了嘗試自己動手用react來寫一個分頁組件(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • React網(wǎng)絡(luò)請求發(fā)起方法詳細(xì)介紹

    React網(wǎng)絡(luò)請求發(fā)起方法詳細(xì)介紹

    在編程開發(fā)中,網(wǎng)絡(luò)數(shù)據(jù)請求是必不可少的,這篇文章主要介紹了React網(wǎng)絡(luò)請求發(fā)起方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-09-09
  • React ts模式使用http-proxy-middleware代理時訪問報404問題

    React ts模式使用http-proxy-middleware代理時訪問報404問題

    這篇文章主要介紹了React ts模式使用http-proxy-middleware代理時訪問報404問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 基于React實現(xiàn)調(diào)用式Modal組件的全流程

    基于React實現(xiàn)調(diào)用式Modal組件的全流程

    本文基于 nextUI 和 tailwindCSS 實現(xiàn)調(diào)用式 Modal 組件的封裝,文中通過圖文結(jié)合的方式和代碼示例介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2024-12-12
  • React-Router如何進(jìn)行頁面權(quán)限管理的方法

    React-Router如何進(jìn)行頁面權(quán)限管理的方法

    本篇文章主要介紹了React-Router如何進(jìn)行頁面權(quán)限管理的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • React-redux?中useSelector使用源碼分析

    React-redux?中useSelector使用源碼分析

    在一個 action 被分發(fā)(dispatch) 后,useSelector() 默認(rèn)對 select 函數(shù)的返回值進(jìn)行引用比較 ===,并且僅在返回值改變時觸發(fā)重渲染,,這篇文章主要介紹了React-redux?中useSelector使用,需要的朋友可以參考下
    2023-10-10

最新評論

开封县| 冷水江市| 孙吴县| 玉环县| 民乐县| 银川市| 东安县| 突泉县| 兴和县| 麦盖提县| 广州市| 诸城市| 马尔康县| 武义县| 乌拉特后旗| 新昌县| 勃利县| 泽普县| 嘉黎县| 天门市| 泌阳县| 彩票| 广安市| 田林县| 读书| 会理县| 安新县| 嘉定区| 安陆市| 石景山区| 萨嘎县| 孟村| 江孜县| 柏乡县| 榆中县| 哈巴河县| 霸州市| 平乡县| 司法| 南昌市| 中山市|