国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

React 服務(wù)端渲染如此輕松 從零開(kāi)始構(gòu)建前后端應(yīng)用

chinafgj / 954人閱讀

摘要:今天這篇文章顯然不是討論這兩個(gè)詞語(yǔ)的,我們要嘗試使用最新版,構(gòu)件一個(gè)簡(jiǎn)單的服務(wù)端渲染應(yīng)用。這樣取代了完全由客戶(hù)端渲染前后端分離方式模式。在場(chǎng)景下,我們可以使用自身的完成服務(wù)端初次渲染。這也是它在推出短短時(shí)間以來(lái),便迅速走紅的原因之一。

參加或留意了最近舉行的JSConf CN 2017的同學(xué),想必對(duì) Next.js 不再陌生, Next.js 的作者之一到場(chǎng)進(jìn)行了精彩的演講。其實(shí)在更早些時(shí)候,由 Facebook 舉辦的 React Conf 2017,他就到場(chǎng)并有近40分鐘的分享。但兩次分享帶來(lái)的 demo 都是 hacker news。我觀察 Next.js 時(shí)間較長(zhǎng),看著它從1.x 版本一直到了今天的 3.x,終于決定寫(xiě)一篇入門(mén)級(jí)的新手指導(dǎo)文章。而這篇文章試圖通過(guò)一個(gè)全新的例子,來(lái)讓大家了解 Next.js 到底是如何與 React 配合,達(dá)到服務(wù)端渲染的。

“React universal” 是社區(qū)上形容基于 React 構(gòu)建 web 應(yīng)用,并采用“服務(wù)端渲染”方式的一個(gè)詞語(yǔ)。也許很多人對(duì) “isomorphic” 這個(gè)單詞更加熟悉,其實(shí)這兩個(gè)詞語(yǔ)想要表達(dá)的概念類(lèi)似。今天這篇文章顯然不是討論這兩個(gè)詞語(yǔ)的,我們要嘗試使用最新版 Next.js,構(gòu)件一個(gè)簡(jiǎn)單的服務(wù)端渲染 React 應(yīng)用。最終項(xiàng)目地址可以點(diǎn)擊這里查看。

為何要開(kāi)發(fā) Universal 應(yīng)用?

React app 實(shí)現(xiàn)了虛擬 DOM,來(lái)實(shí)現(xiàn)對(duì)真實(shí) DOM 的抽象。這樣的設(shè)計(jì)迅速引領(lǐng)了前端開(kāi)發(fā)浪潮。但是 “Every great thing comes with a price”,虛擬 DOM 同樣帶來(lái)了一些弊端,比如在前后端分離的開(kāi)發(fā)模式下,SEO就成了問(wèn)題;同樣首屏加載時(shí)間變長(zhǎng),各種 loading 消磨人的耐心。就像下面截圖所展現(xiàn)的那樣:

使用 Next.js 實(shí)現(xiàn) Universal

Universal 應(yīng)用架構(gòu)可以簡(jiǎn)單粗暴先而片面的理解成應(yīng)用將在客戶(hù)端和服務(wù)端共同完成渲染。這樣取代了完全由客戶(hù)端渲染(前后端分離方式)模式。在 React 場(chǎng)景下,我們可以使用 React 自身的 renderToString 完成服務(wù)端初次渲染。但是如果我們每次手動(dòng)來(lái)完成這些過(guò)程,手動(dòng)實(shí)現(xiàn)服務(wù)端繁瑣配置,難免令人頭大心煩。

Next.js 的出現(xiàn),就是為你解決這種惱人的問(wèn)題。我們先來(lái)認(rèn)識(shí)一下它的幾個(gè)原則和思想:

不需要除 Next 之外,多余的配置和安裝(比如 webpack,babel);

使用 Glamor 處理樣式;

自動(dòng)編譯和打包;

熱更新;

方便的靜態(tài)資源管理;

成熟靈活的路由配置,包括路由級(jí)別 prefetching;

Demo:英超聯(lián)賽積分榜

其實(shí)關(guān)于更多的 Next.js 設(shè)計(jì)理念我不想再贅述了,讀者都可以在其官網(wǎng)找到豐富的內(nèi)容。下面,我將使用 Football Data API 來(lái)簡(jiǎn)單開(kāi)發(fā)一個(gè)基于 Next.js 的應(yīng)用,這個(gè)應(yīng)用將展現(xiàn)英超聯(lián)賽的實(shí)時(shí)積分榜。同時(shí)包含了簡(jiǎn)單的路由開(kāi)發(fā)和頁(yè)面跳轉(zhuǎn)。

小試牛刀

相信所有的開(kāi)發(fā)者都厭惡超長(zhǎng)時(shí)間的安裝和各種依賴(lài)、插件配置。不要擔(dān)心,Next.js 作為一個(gè)獨(dú)立的 npm package 最大限度的替你完成了很多耗時(shí)且無(wú)趣的工作。我們首先需要進(jìn)行安裝:

# Start a new project
npm init
# Install Next.js
npm install next --save

安裝結(jié)束后,我們就可以開(kāi)啟腳本:

"scripts": {
   "start": "next"
 },
 

Next 安裝的同時(shí),也會(huì)安裝 React,所以無(wú)需自己費(fèi)心。接下來(lái)所需要做的很簡(jiǎn)單,就是在根目錄下創(chuàng)建一個(gè) pages 文件夾,并在其下新建一個(gè) index.js 文件:

// ./pages/index.js

// Import React
import React from "react"

// Export an anonymous arrow function
// which returns the template
export default () => (
  

This is just so easy!

)

好了,現(xiàn)在就可以直接看到結(jié)果:

# Start your app
npm start

驗(yàn)證一下它來(lái)自服務(wù)端渲染:

就是這么簡(jiǎn)單,清新。如果我們自己手段實(shí)現(xiàn)這一切的話,除了 NodeJS 的種種繁瑣不說(shuō),webpack 配置,node_modules 依賴(lài),babel插件等等就夠折騰半天的了。

添加 Page Head

在 ./pages/index.js 文件內(nèi),我們可以添加頁(yè)面 head 標(biāo)簽、meta 信息、樣式資源等等:

// ./pages/index.js
import React from "react"
// Import the Head Component
import Head from "next/head"

export default () => (
  
League Table

This is just so easy!

)

這個(gè) head 當(dāng)然不是指真實(shí)的 DOM,千萬(wàn)別忘了 React 虛擬 DOM 的概念。其實(shí)這是 Next 提供的 Head 組件,不過(guò)最終一定還是被渲染成為真實(shí)的 head 標(biāo)簽。

發(fā)送 Ajax 請(qǐng)求

Next 還提供了 getInitialProps 方法,這個(gè)方法支持異步選項(xiàng),并且是服務(wù)端/客戶(hù)端同構(gòu)的。我們可以使用 async/await 方式,處理異步請(qǐng)求。請(qǐng)看下面的示例:

import React from "react"
import Head from "next/head"
import axios from "axios";

export default class extends React.Component {
    // Async operation with getInitialProps
    static async getInitialProps () {
        // res is assigned the response once the axios
        // async get is completed
        const res = await axios.get("http://api.football-data.org/v1/competitions/426/leagueTable");
        // Return properties
        return {data: res.data}
      }
 }
 

我們使用了 axios 類(lèi)庫(kù)來(lái)發(fā)送 HTTP 請(qǐng)求。網(wǎng)絡(luò)請(qǐng)求是異步的,因此我們需要在未來(lái)某個(gè)合適的時(shí)候(請(qǐng)求結(jié)果返回時(shí))接收數(shù)據(jù)。這里使用先進(jìn)的 async/await,以同步的方式處理,從而避免了回調(diào)嵌套和 promises 鏈。

我們將異步獲得的數(shù)據(jù)返回,它將自動(dòng)掛載在 props 上(注意 getInitialProps 方法名,顧名思義),render 方法里便可以通過(guò) this.props.data 獲取:

import React from "react"
import Head from "next/head"
import axios from "axios";

export default class extends React.Component {
  static async getInitialProps () {
    const res = await axios.get("http://api.football-data.org/v1/competitions/426/leagueTable");
    return {data: res.data}
  }
  render () {
    return (
      
......

Barclays Premier League

...... {this.props.data.standing.map((standing, i) => { const oddOrNot = i % 2 == 1 ? "pure-table-odd" : ""; return ( ); })}
{standing.position} {standing.points} {standing.goals} {standing.wins} {standing.draws} {standing.losses}
); } }

這樣,再訪問(wèn)我們的頁(yè)面,就有了:

路由和頁(yè)面跳轉(zhuǎn)

也許你已經(jīng)有所感知:我們已經(jīng)有了最基本的一個(gè)路由。Next 不需要任何額外的路由配置信息,你只需要在 pages 文件夾下新建文件,每一個(gè)文件都將是一個(gè)獨(dú)立的頁(yè)面。

讓我們來(lái)新建一個(gè) team 頁(yè)面吧!新建 ./pages/details.js 文件:

// ./pages/details.js
import React from "react"
export default () => (
  

Coming soon. . .!

)

我們使用 Next 已經(jīng)準(zhǔn)備好的組件 來(lái)進(jìn)行頁(yè)面跳轉(zhuǎn):

// ./pages/details.js
import React from "react"

// Import Link from next
import Link from "next/link"

export default () => (
  

Coming soon. . .!

Go Home
)

這個(gè)頁(yè)面不能總是 “Coming soon. . .!” 的信息,我們來(lái)進(jìn)行完善以展示更多內(nèi)容,通過(guò)頁(yè)面 URL 的 query id 變量,我們來(lái)請(qǐng)求并展現(xiàn)當(dāng)前相應(yīng)隊(duì)伍的信息:

import React from "react"
import Head from "next/head"
import Link from "next/link"
import axios from "axios";

export default class extends React.Component {
    static async getInitialProps ({query}) {
        // Get id from query
        const id = query.id;
        if(!process.browser) {
            // Still on the server so make a request
            const res = await axios.get("http://api.football-data.org/v1/competitions/426/leagueTable")
            return {
                data: res.data,
                // Filter and return data based on query
                standing: res.data.standing.filter(s => s.position == id)
            }
        } else {
            // Not on the server just navigating so use
            // the cache
            const bplData = JSON.parse(sessionStorage.getItem("bpl"));
            // Filter and return data based on query
            return {standing: bplData.standing.filter(s => s.position == id)}
        }
    }

    componentDidMount () {
        // Cache data in localStorage if
        // not already cached
        if(!sessionStorage.getItem("bpl")) sessionStorage.setItem("bpl", JSON.stringify(this.props.data))
    }

    // . . . render method truncated
 }

這個(gè)頁(yè)面根據(jù) query 變量,動(dòng)態(tài)展現(xiàn)出球隊(duì)信息。具體來(lái)看,getInitialProps 方法獲取 URL query id,根據(jù) id 篩選出(filter 方法)展示信息。有意思的是,因?yàn)橐恢鼻蜿?duì)的信息比較穩(wěn)定,所以在客戶(hù)端使用了 sessionStorage 進(jìn)行存儲(chǔ)。

完整的 render 方法:

// . . . truncated

export default class extends React.Component {
    // . . . truncated
    render() {

        const detailStyle = {
            ul: {
                marginTop: "100px"
            }
        }

        return  (
             
League Table

{this.props.standing[0].teamName}

Points: {this.props.standing[0].points}

  • Goals: {this.props.standing[0].goals}
  • Wins: {this.props.standing[0].wins}
  • Losses: {this.props.standing[0].losses}
  • Draws: {this.props.standing[0].draws}
  • Goals Against: {this.props.standing[0].goalsAgainst}
  • Goal Difference: {this.props.standing[0].goalDifference}
  • Played: {this.props.standing[0].playedGames}
Home
) } }

注意下面截圖中,同一頁(yè)面不同 query 值,分別展示了冠軍?切爾西和曼聯(lián)的信息。

別忘了我們的主頁(yè)(排行榜頁(yè)面)index.js 中,也要使用相應(yīng)的 sessionStorage 邏輯。同時(shí),在 render 方法里加入一條鏈接到詳情頁(yè)的

More...

錯(cuò)誤頁(yè)面

在 Next 中,我們同樣可以通過(guò) error.js 文件定義錯(cuò)誤頁(yè)面。在 ./pages 下新建 error.js:

// ./pages/_error.js
import React from "react"

export default class Error extends React.Component {
  static getInitialProps ({ res, xhr }) {
    const statusCode = res ? res.statusCode : (xhr ? xhr.status : null)
    return { statusCode }
  }

  render () {
    return (
      

{ this.props.statusCode ? `An error ${this.props.statusCode} occurred on server` : "An error occurred on client" }

) } }

當(dāng)傳統(tǒng)情況下頁(yè)面404時(shí),得到:

在我們?cè)O(shè)置 _ error.js 之后,便有:

總結(jié)

這篇文章實(shí)現(xiàn)了一個(gè)簡(jiǎn)易 demo,只是介紹了最基本的 Next.JS 搭建 React 同構(gòu)應(yīng)用的基本步驟。

想想你是否厭煩了 webpack 惱人的配置?是否對(duì)于 Babel 各種插件云里霧里?
使用 Next.js,簡(jiǎn)單、清新而又設(shè)計(jì)良好。這也是它在推出短短時(shí)間以來(lái),便迅速走紅的原因之一。

除此之外,Next 還有非常多的功能,非常多的先進(jìn)理念可以應(yīng)用。

比如 搭配 prefetch,預(yù)先請(qǐng)求資源;

再如動(dòng)態(tài)加載組件(Next.js 支持 TC39 dynamic import proposal),從而減少首次 bundle size;

雖然它替我們封裝好了 Webpack、Babel 等工具,但是我們又能 customizing,根據(jù)需要自定義。

最后,對(duì)于這些本文章沒(méi)有演示到的功能是否有些手癢?感興趣的讀者可以關(guān)注本文 demo 的Github項(xiàng)目地址,自己手動(dòng)嘗試起來(lái)吧~

本文意譯了Chris Nwamba的:React Universal with Next.js: Server-side React 一文,并對(duì)原文進(jìn)行了升級(jí),兼容了最新的 Next 設(shè)計(jì)。

我的其他關(guān)于 React 文章:

做出Uber移動(dòng)網(wǎng)頁(yè)版還不夠 極致性能打造才見(jiàn)真章

解析Twitter前端架構(gòu) 學(xué)習(xí)復(fù)雜場(chǎng)景數(shù)據(jù)設(shè)計(jì)

React Conf 2017 干貨總結(jié)1: React + ES next = ?

React+Redux打造“NEWS EARLY”單頁(yè)應(yīng)用 一個(gè)項(xiàng)目理解最前沿技術(shù)棧真諦

一個(gè)react+redux工程實(shí)例

Happy Coding!

PS:
作者Github倉(cāng)庫(kù) 和 知乎問(wèn)答鏈接
歡迎各種形式交流。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/51023.html

相關(guān)文章

  • React 服務(wù)渲染如此輕松 從零開(kāi)始構(gòu)建前后應(yīng)用

    摘要:今天這篇文章顯然不是討論這兩個(gè)詞語(yǔ)的,我們要嘗試使用最新版,構(gòu)件一個(gè)簡(jiǎn)單的服務(wù)端渲染應(yīng)用。這樣取代了完全由客戶(hù)端渲染前后端分離方式模式。在場(chǎng)景下,我們可以使用自身的完成服務(wù)端初次渲染。這也是它在推出短短時(shí)間以來(lái),便迅速走紅的原因之一。 參加或留意了最近舉行的JSConf CN 2017的同學(xué),想必對(duì) Next.js 不再陌生, Next.js 的作者之一到場(chǎng)進(jìn)行了精彩的演講。其實(shí)在更早...

    binaryTree 評(píng)論0 收藏0
  • 從零構(gòu)建前后分離web項(xiàng)目》:開(kāi)篇 - 縱觀WEB歷史演變

    摘要:更詳細(xì)的內(nèi)容下一章開(kāi)篇深入聊聊前后分離講述關(guān)于我目前在寫(xiě)從零構(gòu)建前后分離項(xiàng)目系列,修正和補(bǔ)充以此為準(zhǔn)不斷更新的項(xiàng)目實(shí)踐地址彩蛋提前預(yù)覽下一章傳送門(mén) 開(kāi)篇 : 縱觀WEB歷史演變 在校學(xué)習(xí)和幾年工作工作中不知不覺(jué)經(jīng)歷了一半的 WEB 歷史演變、對(duì)近幾年的發(fā)展比較了解,結(jié)合經(jīng)驗(yàn)聊聊 WEB 發(fā)展歷史。 演變不易,但也是必然,因?yàn)闉槿耸冀K要進(jìn)步。 WEB 的發(fā)展史 一、開(kāi)山鼻祖 - 石器時(shí)代...

    tracy 評(píng)論0 收藏0
  • 從零構(gòu)建前后分離web項(xiàng)目》:開(kāi)篇 - 縱觀WEB歷史演變

    摘要:更詳細(xì)的內(nèi)容下一章開(kāi)篇深入聊聊前后分離講述關(guān)于我目前在寫(xiě)從零構(gòu)建前后分離項(xiàng)目系列,修正和補(bǔ)充以此為準(zhǔn)不斷更新的項(xiàng)目實(shí)踐地址彩蛋提前預(yù)覽下一章傳送門(mén) 開(kāi)篇 : 縱觀WEB歷史演變 在校學(xué)習(xí)和幾年工作工作中不知不覺(jué)經(jīng)歷了一半的 WEB 歷史演變、對(duì)近幾年的發(fā)展比較了解,結(jié)合經(jīng)驗(yàn)聊聊 WEB 發(fā)展歷史。 演變不易,但也是必然,因?yàn)闉槿耸冀K要進(jìn)步。 WEB 的發(fā)展史 一、開(kāi)山鼻祖 - 石器時(shí)代...

    songjz 評(píng)論0 收藏0
  • 2017-07-19 前日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選開(kāi)發(fā)常見(jiàn)問(wèn)題集錦前端碼農(nóng)的自我修養(yǎng)虛擬內(nèi)部是如何工作的譯知乎專(zhuān)欄并不慢,只是你使用姿勢(shì)不對(duì)一份優(yōu)化指南掘金老司機(jī)帶你秒懂內(nèi)存管理第一部中文免費(fèi)公開(kāi)課前端面試的大關(guān)鍵點(diǎn),你到了嗎知乎專(zhuān)欄高效開(kāi)發(fā)與設(shè)計(jì)姐的圖片二三 2017-07-19 前端日?qǐng)?bào) 精選 VueJS 開(kāi)發(fā)常見(jiàn)問(wèn)題集錦 - 前端碼農(nóng)的自我修養(yǎng) - SegmentFault虛擬 DOM 內(nèi)部是如何工作的?[譯]Hig...

    iflove 評(píng)論0 收藏0
  • React Redux 中間件思想遇見(jiàn) Web Worker 的靈感(附demo)

    摘要:寫(xiě)在最前原文首發(fā)于作者的知乎專(zhuān)欄中間件思想遇見(jiàn)的靈感附,感興趣的同學(xué)可以知乎關(guān)注,進(jìn)行交流。其中,最重要的一個(gè)便是對(duì)多線程的支持。在中提出了工作線程的概念,并且規(guī)范出的三大主要特征能夠長(zhǎng)時(shí)間運(yùn)行響應(yīng)理想的啟動(dòng)性能以及理想的內(nèi)存消耗。 寫(xiě)在最前 原文首發(fā)于作者的知乎專(zhuān)欄:React Redux 中間件思想遇見(jiàn) Web Worker 的靈感(附demo),感興趣的同學(xué)可以知乎關(guān)注,進(jìn)行交流...

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

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

0條評(píng)論

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