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

資訊專(zhuān)欄INFORMATION COLUMN

nextjs踩坑

JayChen / 691人閱讀

摘要:踩坑幾乎一整年沒(méi)咋寫(xiě)文章,主要是懶,加上工作也挺忙。遇到一些坑,也有一些收獲這里記錄一下。個(gè)人習(xí)慣使用啟動(dòng)服務(wù)。總結(jié)說(shuō)了上面那么多,其實(shí)官方文檔里都有相關(guān)例子,就當(dāng)我的個(gè)人踩坑記錄吧。

Next.js踩坑

幾乎一整年沒(méi)咋寫(xiě)文章,主要是懶,加上工作也挺忙。但是想趁著年底發(fā)一篇,希望明年更勤奮一點(diǎn)。其實(shí)不是沒(méi)東西寫(xiě),就是想深入一個(gè)東西還是很困難的,要查各種資料,最終還是懶就是了。

next.js是react的同構(gòu)庫(kù),很多文章里把他當(dāng)作一個(gè)腳手架,也不是不行,但是個(gè)人認(rèn)為next.js比一般的腳手架能做的更多,但也有局限性。這兩天下班回去實(shí)踐了一下nextjs的開(kāi)發(fā)。遇到一些坑,也有一些收獲這里記錄一下。

請(qǐng)求數(shù)據(jù)

nextjs沒(méi)有客戶(hù)端的生命周期,只有一個(gè)靜態(tài)方法getInitialProps,所以獲取接口數(shù)據(jù)也只能在這個(gè)方法里了。getInitialProps的返回?cái)?shù)據(jù)就作為該組件的props。getInitialProps有兩個(gè)參數(shù):req和res,也就是我們非常熟悉的http參數(shù)。說(shuō)句題外話(huà),現(xiàn)有的node web框架都是req作為輸入,res作為輸出,增加各種中間件。

所以個(gè)人覺(jué)得nextjs的組件形式太適合無(wú)狀態(tài)組件了。下面是一個(gè)簡(jiǎn)單的例子代碼:

// 獲取電影列表并渲染
class MovieList extends Component {
    static async getInitialProps(){
      const data = await getMovieList()
    return {
        list: data
    }
  }
  
  render () {
      return (
        
{this.props.list.map(movie => { })}
) } }

當(dāng)然這里最終僅僅是服務(wù)端輸出的列表,我們可能還會(huì)有其他操作,比如刪除加載下一頁(yè)之類(lèi)的,但是這些操作都沒(méi)必要在服務(wù)端操作的。添加幾個(gè)相應(yīng)的方法即可。

路由管理

nextjs的路由是基于文件系統(tǒng)的,相當(dāng)清晰和簡(jiǎn)單,比如在pages文件夾下面增加一個(gè)movie-detail組件,并寫(xiě)上相應(yīng)的代碼,我們就可以訪(fǎng)問(wèn)/movie-detail 這個(gè)路由了。起初覺(jué)得這樣的路由形式實(shí)在太優(yōu)雅了,但是用久了就會(huì)發(fā)現(xiàn)很多問(wèn)題。

路由嵌套

首先是嵌套路由,比如我想建立/user/profile這個(gè)路由,這個(gè)其實(shí)很好解決,就是在pages文件夾下面依次嵌套就行了:

具名路由

其次是沒(méi)有官方實(shí)現(xiàn)具名路徑,什么是具名路徑呢?就是/movie/:id這里這種形式,個(gè)人感覺(jué)nextjs在這方面是追隨react-router4的。vuejs的同構(gòu)框架nuxtjs則不存在這個(gè)問(wèn)題,因?yàn)関ue-router本身也是統(tǒng)一管理路由的。先不說(shuō)這種情況的好壞,還是找找解決方案吧。

根據(jù)我找到的實(shí)例和文檔,目前有兩種解決方案:

使用query代替具名路

下圖可以看到其實(shí)在nextjs router里query是存在的。

那我們需要訪(fǎng)問(wèn)具名路由頁(yè)面的時(shí)候可以這么寫(xiě), 將id用query傳過(guò)去/movie-detail?id=xxx

// 電影詳情頁(yè)面

class MovieDetail extends Component {
    static async getInitialProps({ req }) {
    const { id } = req.query
    const detail = await getDetail(id) 
      return {
        detail
    }
  }
  
  render () {
      return (
        // do anything you want
    )
  }
}
custom server 解決

使用query傳參數(shù)過(guò)去確實(shí)可以解決問(wèn)題,但是太不優(yōu)雅,與rest的思想也不太符合。所以next社區(qū)找到了另一個(gè)解決方案,使用custom server。

在說(shuō)具體方案之前我們我們可以了解一下,說(shuō)到底nextjs并不是一個(gè)生成靜態(tài)資源的腳手架,next最終還是要多帶帶部署node服務(wù)的。也就是nextjs其實(shí)內(nèi)置了一個(gè)http服務(wù),如果我們不使用custom sever的話(huà),內(nèi)置服務(wù)還是可以很好的幫我們完成渲染頁(yè)面的任務(wù)。

但是如果我們的node不僅僅是渲染頁(yè)面,還需要寫(xiě)接口。那么這時(shí)候的情況就很類(lèi)似傳統(tǒng)后端的開(kāi)發(fā)模式了:不僅僅需要寫(xiě)接口還需要渲染頁(yè)面。

很顯然nextjs的內(nèi)置http服務(wù)是無(wú)法完成這個(gè)任務(wù)的,我們需要更加完善的web 框架。畢竟專(zhuān)業(yè)的事還是交給專(zhuān)業(yè)的。這時(shí)候就是custom server大顯身手的時(shí)候了。nextjs里也有一系列的例子:

那么custom server是如何解決具名路徑的問(wèn)題的呢?我們是借用nextjs的渲染能力。這里以express為例,具體代碼如下:

// server.js
const express = require("express")
const next = require("next")

const dev = process.env.NODE_ENV !== "production"
const app = next({ dev, quiet: false })
const handle = app.getRequestHandler()
const SERVE_PORT = process.env.SERVE_PORT || 8001

app.prepare().then(() => {
  const server = express()

  server.get("/movie-detail/:id", async (req, res) => {
    // 渲染movie-detail這個(gè)組件
    const html = await app.renderToHTML(req, res, "/movie-detail", req.query)
    res.send(html)
  })

  server.get("*", (req, res) => handle(req, res))

  server.listen(SERVE_PORT, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${SERVE_PORT}`)
  })
})

上面是server.js的簡(jiǎn)略代碼,當(dāng)然在組件里我們也要做相應(yīng)處理,代碼如下

// /pages/movie-detail.jsx
// 電影詳情頁(yè)面

class MovieDetail extends Component {
    static async getInitialProps({ req }) {
    const { id } = req.params
    const detail = await getDetail(id) 
      return {
        detail,
      id
    }
  }
  
  render () {
      return (
        // do anything you want
    )
  }
}
頁(yè)面緩存

對(duì)于csr的的react應(yīng)用來(lái)說(shuō),渲染耗時(shí)100ms并不是什么太大問(wèn)題,但是到了服務(wù)端,100ms很明顯是沒(méi)法忍受的。首先客戶(hù)端渲染并不會(huì)造成服務(wù)器資源的浪費(fèi),其實(shí)也不會(huì)對(duì)服務(wù)器造成太大鴨梨。但是服務(wù)端就不一樣了。一旦用戶(hù)量大了,勢(shì)必會(huì)引起各種問(wèn)題,所以頁(yè)面緩存還是很有必要的。

具體頁(yè)面緩存在哪里并不是我們考量的范圍,同樣頁(yè)面緩存也需要用到custom server,具體服務(wù)端框架自定吧。這里以lru-cache為例做一個(gè)簡(jiǎn)單的頁(yè)面緩存,其實(shí)換成其他的諸如redis也是沒(méi)有任何問(wèn)題的。

const dev = process.env.NODE_ENV !== "production"

const next = require("next")
const express = require("express")
const LRUCache = require("lru-cache")

const ssrCache = new LRUCache({
  max: 1000, // cache item count
  maxAge: 1000 * 60 * 60, // 1 hour
})

const app = next({ dev, quiet: false })

const handle = app.getRequestHandler()

const SERVE_PORT = process.env.SERVE_PORT || 8001

app.prepare().then(() => {
  const server = express()

  server.get("/", async (req, res) => {
    renderAndCache(req, res, "/", { ...req.query })    
  })

  server.get("/movie-detail/:id", async (req, res) => {
    renderAndCache(req, res, "/movie-detail", { ...req.query })
  })

  server.get("*", (req, res) => handle(req, res))

  server.listen(SERVE_PORT, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${SERVE_PORT}`)
  })
})

const getCacheKey = req => `${req.url}`

// 緩存并渲染頁(yè)面,具體是重新渲染還是使用緩存
async function renderAndCache(req, res, pagePath, queryParams) {
  const key = getCacheKey(req)
  if (ssrCache.has(key)) {
    res.setHeader("x-cache", "HIT")
    res.send(ssrCache.get(key))
    return
  }

  try {
    const html = await app.renderToHTML(req, res, pagePath, queryParams)

    // Something is wrong with the request, let"s skip the cache
    if (res.statusCode !== 200) {
      res.send(html)
      return
    }

    // Let"s cache this page
    ssrCache.set(key, html)

    res.setHeader("x-cache", "MISS")
    res.send(html)
  } catch (err) {
    app.renderError(err, req, res, pagePath, queryParams)
  }
}

其中renderAndCache是關(guān)鍵。這里判斷頁(yè)面是否有緩存,如果有的話(huà)則直出緩存內(nèi)容。否則的話(huà)就重新渲染。至于緩存時(shí)間還有緩存大小看個(gè)人設(shè)置了,這里不贅述了。

部署上線(xiàn)

部署上線(xiàn)這一塊實(shí)在沒(méi)什么好說(shuō)的,簡(jiǎn)單的話(huà)直接起一個(gè)node服務(wù)的就可以,復(fù)雜一點(diǎn)就要包括報(bào)警重啟等等,都是看個(gè)人情況的。

個(gè)人習(xí)慣使用supervisor啟動(dòng)node服務(wù)。

總結(jié)

說(shuō)了上面那么多,其實(shí)官方文檔里都有相關(guān)例子,就當(dāng)我的個(gè)人踩坑記錄吧。

對(duì)于nextjs來(lái)說(shuō),我認(rèn)為如果是展示型的應(yīng)用,就應(yīng)該放心大膽的用起來(lái)。不光開(kāi)發(fā)快還爽,同時(shí)屏蔽webpack配置,有什么理由不用?

如果是功能性的,比如一系列的繪圖組件則完成沒(méi)必要使用了,對(duì)于canvas之類(lèi)的還是必須用客戶(hù)端渲染,然而nextjs又沒(méi)有生命周期,用nextjs可能會(huì)相當(dāng)坑。

對(duì)于個(gè)人開(kāi)發(fā)這我則是相當(dāng)推薦。何必去配置webpack浪費(fèi)生命啊。

如果是完全靜態(tài)的應(yīng)用,我推薦gatsbyjs。具體怎么使用則是另外一個(gè)話(huà)題了。

如有謬誤,輕點(diǎn)噴。 over

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

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

相關(guān)文章

  • Next.js踩坑入門(mén)系列(一)— Hello Next.js!

    摘要:接下來(lái)我們運(yùn)行一下。因此,我們需要新建一個(gè)目錄。接下在再重新啟動(dòng)一下試試。因?yàn)槟J(rèn)開(kāi)啟服務(wù)端渲染,也就無(wú)需我們進(jìn)行任何的配置,因此現(xiàn)在這個(gè)極其簡(jiǎn)單的應(yīng)用就是一個(gè)。代碼地址參考文章服務(wù)端渲染與打造高可靠與高性能的同構(gòu)解決方案 寫(xiě)在前面 說(shuō)實(shí)話(huà),我個(gè)人還是覺(jué)得文筆越來(lái)越不錯(cuò)了,以前的文章都是一個(gè)問(wèn)題悶到天黑,文章寫(xiě)的有點(diǎn)亂由于文章過(guò)于龐大導(dǎo)致不是一氣呵成的,思路有時(shí)候會(huì)很混亂。所以我也準(zhǔn)備...

    rockswang 評(píng)論0 收藏0
  • 這是一個(gè)快速構(gòu)建nextjs應(yīng)用的工具

    摘要:官方也有一個(gè)的工具,但是只能簡(jiǎn)單的安裝基礎(chǔ)的依賴(lài),或者通過(guò)他們提供的某個(gè)例子來(lái)構(gòu)建自己的項(xiàng)目。由于目前還在開(kāi)發(fā)階段只支持上面這些的配置也是平常我用的比較多的配置。 因?yàn)楣镜臉I(yè)務(wù)需求現(xiàn)在開(kāi)發(fā)都用nextjs來(lái)實(shí)現(xiàn)React的服務(wù)端渲染,為了之后開(kāi)發(fā)方便自己寫(xiě)了個(gè)腳手架工具。 官方也有一個(gè)create-next-app的工具,但是只能簡(jiǎn)單的安裝基礎(chǔ)的依賴(lài),或者通過(guò)他們提供的某個(gè)例子來(lái)構(gòu)建...

    scola666 評(píng)論0 收藏0
  • Next.js之基礎(chǔ)概念(二)

    摘要:樣式在中寫(xiě)樣式,一般可以歸為類(lèi),一類(lèi)是基于文件的傳統(tǒng)方式包括,等,另一類(lèi)則是。我們回到我們的代碼中,更改,代碼如下在標(biāo)簽中,我們寫(xiě)我們的,必須包含在中,否則會(huì)報(bào)錯(cuò)。至此,的基礎(chǔ)概念已經(jīng)介紹完了,更高級(jí)的用法,可以參考官方的例子。 本篇教程基于上一篇的基礎(chǔ),主要講解服務(wù)端渲染,樣式以及部署相關(guān)的一些知識(shí),若你沒(méi)有看過(guò)上一篇的內(nèi)容,或者你看過(guò)又忘了,建議重新去看一遍。 順便說(shuō)一句,Next...

    DirtyMind 評(píng)論0 收藏0
  • Next.js之基礎(chǔ)概念

    摘要:是一個(gè)基于實(shí)現(xiàn)的服務(wù)端渲染框架,地址為。本文先從簡(jiǎn)單地基礎(chǔ)概念開(kāi)始,一步一步帶大家認(rèn)識(shí)。本篇教程到此結(jié)束,后面會(huì)跟大家介紹的服務(wù)端渲染及以及部署相關(guān)的一下概念及示例代碼。 Next.js是一個(gè)基于React實(shí)現(xiàn)的服務(wù)端渲染框架,github地址為next.js。 使用Next.js實(shí)現(xiàn)服務(wù)端渲染是一件非常簡(jiǎn)單的事,在這里,你完全可以不用自己去寫(xiě)webpack等配置,Next.js全都幫...

    2bdenny 評(píng)論0 收藏0
  • Nextjs中文文檔

    摘要:中文站點(diǎn)中文站當(dāng)前翻譯版本為。注意將不能使用在子組件中。只能使用在頁(yè)面中。替換路由組件默認(rèn)將新推入路由棧中。以防服務(wù)端渲染發(fā)生錯(cuò)誤,建議事件寫(xiě)在生命周期里。禁止文件路由默認(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

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

0條評(píng)論

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