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

資訊專欄INFORMATION COLUMN

React 服務端渲染如此輕松 從零開始構建前后端應用

binaryTree / 2664人閱讀

摘要:今天這篇文章顯然不是討論這兩個詞語的,我們要嘗試使用最新版,構件一個簡單的服務端渲染應用。這樣取代了完全由客戶端渲染前后端分離方式模式。在場景下,我們可以使用自身的完成服務端初次渲染。這也是它在推出短短時間以來,便迅速走紅的原因之一。

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

“React universal” 是社區上形容基于 React 構建 web 應用,并采用“服務端渲染”方式的一個詞語。也許很多人對 “isomorphic” 這個單詞更加熟悉,其實這兩個詞語想要表達的概念類似。今天這篇文章顯然不是討論這兩個詞語的,我們要嘗試使用最新版 Next.js,構件一個簡單的服務端渲染 React 應用。最終項目地址可以點擊這里查看。

為何要開發 Universal 應用?

React app 實現了虛擬 DOM,來實現對真實 DOM 的抽象。這樣的設計迅速引領了前端開發浪潮。但是 “Every great thing comes with a price”,虛擬 DOM 同樣帶來了一些弊端,比如在前后端分離的開發模式下,SEO就成了問題;同樣首屏加載時間變長,各種 loading 消磨人的耐心。就像下面截圖所展現的那樣:

使用 Next.js 實現 Universal

Universal 應用架構可以簡單粗暴先而片面的理解成應用將在客戶端和服務端共同完成渲染。這樣取代了完全由客戶端渲染(前后端分離方式)模式。在 React 場景下,我們可以使用 React 自身的 renderToString 完成服務端初次渲染。但是如果我們每次手動來完成這些過程,手動實現服務端繁瑣配置,難免令人頭大心煩。

Next.js 的出現,就是為你解決這種惱人的問題。我們先來認識一下它的幾個原則和思想:

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

使用 Glamor 處理樣式;

自動編譯和打包;

熱更新;

方便的靜態資源管理;

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

Demo:英超聯賽積分榜

其實關于更多的 Next.js 設計理念我不想再贅述了,讀者都可以在其官網找到豐富的內容。下面,我將使用 Football Data API 來簡單開發一個基于 Next.js 的應用,這個應用將展現英超聯賽的實時積分榜。同時包含了簡單的路由開發和頁面跳轉。

小試牛刀

相信所有的開發者都厭惡超長時間的安裝和各種依賴、插件配置。不要擔心,Next.js 作為一個獨立的 npm package 最大限度的替你完成了很多耗時且無趣的工作。我們首先需要進行安裝:

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

安裝結束后,我們就可以開啟腳本:

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

Next 安裝的同時,也會安裝 React,所以無需自己費心。接下來所需要做的很簡單,就是在根目錄下創建一個 pages 文件夾,并在其下新建一個 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!

)

好了,現在就可以直接看到結果:

# Start your app
npm start

驗證一下它來自服務端渲染:

就是這么簡單,清新。如果我們自己手段實現這一切的話,除了 NodeJS 的種種繁瑣不說,webpack 配置,node_modules 依賴,babel插件等等就夠折騰半天的了。

添加 Page Head

在 ./pages/index.js 文件內,我們可以添加頁面 head 標簽、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!

)

這個 head 當然不是指真實的 DOM,千萬別忘了 React 虛擬 DOM 的概念。其實這是 Next 提供的 Head 組件,不過最終一定還是被渲染成為真實的 head 標簽。

發送 Ajax 請求

Next 還提供了 getInitialProps 方法,這個方法支持異步選項,并且是服務端/客戶端同構的。我們可以使用 async/await 方式,處理異步請求。請看下面的示例:

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 類庫來發送 HTTP 請求。網絡請求是異步的,因此我們需要在未來某個合適的時候(請求結果返回時)接收數據。這里使用先進的 async/await,以同步的方式處理,從而避免了回調嵌套和 promises 鏈。

我們將異步獲得的數據返回,它將自動掛載在 props 上(注意 getInitialProps 方法名,顧名思義),render 方法里便可以通過 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}
); } }

這樣,再訪問我們的頁面,就有了:

路由和頁面跳轉

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

讓我們來新建一個 team 頁面吧!新建 ./pages/details.js 文件:

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

Coming soon. . .!

)

我們使用 Next 已經準備好的組件 來進行頁面跳轉:

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

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

export default () => (
  

Coming soon. . .!

Go Home
)

這個頁面不能總是 “Coming soon. . .!” 的信息,我們來進行完善以展示更多內容,通過頁面 URL 的 query id 變量,我們來請求并展現當前相應隊伍的信息:

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
 }

這個頁面根據 query 變量,動態展現出球隊信息。具體來看,getInitialProps 方法獲取 URL query id,根據 id 篩選出(filter 方法)展示信息。有意思的是,因為一直球隊的信息比較穩定,所以在客戶端使用了 sessionStorage 進行存儲。

完整的 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
) } }

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

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

More...

錯誤頁面

在 Next 中,我們同樣可以通過 error.js 文件定義錯誤頁面。在 ./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" }

) } }

當傳統情況下頁面404時,得到:

在我們設置 _ error.js 之后,便有:

總結

這篇文章實現了一個簡易 demo,只是介紹了最基本的 Next.JS 搭建 React 同構應用的基本步驟。

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

除此之外,Next 還有非常多的功能,非常多的先進理念可以應用。

比如 搭配 prefetch,預先請求資源;

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

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

最后,對于這些本文章沒有演示到的功能是否有些手癢?感興趣的讀者可以關注本文 demo 的Github項目地址,自己手動嘗試起來吧~

本文意譯了Chris Nwamba的:React Universal with Next.js: Server-side React 一文,并對原文進行了升級,兼容了最新的 Next 設計。

我的其他關于 React 文章:

做出Uber移動網頁版還不夠 極致性能打造才見真章

解析Twitter前端架構 學習復雜場景數據設計

React Conf 2017 干貨總結1: React + ES next = ?

React+Redux打造“NEWS EARLY”單頁應用 一個項目理解最前沿技術棧真諦

一個react+redux工程實例

Happy Coding!

PS:
作者Github倉庫 和 知乎問答鏈接
歡迎各種形式交流。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84131.html

相關文章

  • React 服務渲染如此輕松 從零開始構建前后應用

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

    chinafgj 評論0 收藏0
  • 從零構建前后分離web項目》:開篇 - 縱觀WEB歷史演變

    摘要:更詳細的內容下一章開篇深入聊聊前后分離講述關于我目前在寫從零構建前后分離項目系列,修正和補充以此為準不斷更新的項目實踐地址彩蛋提前預覽下一章傳送門 開篇 : 縱觀WEB歷史演變 在校學習和幾年工作工作中不知不覺經歷了一半的 WEB 歷史演變、對近幾年的發展比較了解,結合經驗聊聊 WEB 發展歷史。 演變不易,但也是必然,因為為人始終要進步。 WEB 的發展史 一、開山鼻祖 - 石器時代...

    tracy 評論0 收藏0
  • 從零構建前后分離web項目》:開篇 - 縱觀WEB歷史演變

    摘要:更詳細的內容下一章開篇深入聊聊前后分離講述關于我目前在寫從零構建前后分離項目系列,修正和補充以此為準不斷更新的項目實踐地址彩蛋提前預覽下一章傳送門 開篇 : 縱觀WEB歷史演變 在校學習和幾年工作工作中不知不覺經歷了一半的 WEB 歷史演變、對近幾年的發展比較了解,結合經驗聊聊 WEB 發展歷史。 演變不易,但也是必然,因為為人始終要進步。 WEB 的發展史 一、開山鼻祖 - 石器時代...

    songjz 評論0 收藏0
  • 2017-07-19 前日報

    摘要:前端日報精選開發常見問題集錦前端碼農的自我修養虛擬內部是如何工作的譯知乎專欄并不慢,只是你使用姿勢不對一份優化指南掘金老司機帶你秒懂內存管理第一部中文免費公開課前端面試的大關鍵點,你到了嗎知乎專欄高效開發與設計姐的圖片二三 2017-07-19 前端日報 精選 VueJS 開發常見問題集錦 - 前端碼農的自我修養 - SegmentFault虛擬 DOM 內部是如何工作的?[譯]Hig...

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

    摘要:寫在最前原文首發于作者的知乎專欄中間件思想遇見的靈感附,感興趣的同學可以知乎關注,進行交流。其中,最重要的一個便是對多線程的支持。在中提出了工作線程的概念,并且規范出的三大主要特征能夠長時間運行響應理想的啟動性能以及理想的內存消耗。 寫在最前 原文首發于作者的知乎專欄:React Redux 中間件思想遇見 Web Worker 的靈感(附demo),感興趣的同學可以知乎關注,進行交流...

    whatsns 評論0 收藏0

發表評論

0條評論

binaryTree

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<