前陣子公司專案從next 3 更新到7、react也從15更新到16,希望能加快開發或佈署的速度,順便分享一下踩到了哪些的地雷。

首先呢,update react、react-dom、next,接下來開始測試一下local build,執行 yarn build,恩…,大概幾隻套件過舊,完全無法編譯,幸好這幾隻套件都有繼續維運,更新一下套件,重新繼續yarn build => yarn start。

node.js

產生 BUILD_ID

發現run起來會抓不到 app.js,發現需要處理路徑問題,舊版next build出來的目錄,不會帶有BUILD_ID,只會在編譯的時候,拿取.next的BUILD_ID來當作路徑,之前是利用docker產生.BUILD_ID。但是新版的會直接寫在folder name上。要使用 generateBuildId 產生buildId,對了,我們buildId內容是git commit hash。

next.js generateBuildId

另外還有react更新,所以eslint相關插件也要更新到新版,花了一些(三天)時間再處理indent跟一些新版的eslint rule。

其餘並沒有改動太大,next.js 拋棄滿多舊有router處理,把專案上有用到部分都移除掉,還有title tag不在_document.js render。

踩坑

心裡想更新react、next還真是簡單,於是乎信心滿滿的更新到正式機上,但是,才發現事情沒有我想的這麼簡單。

當天晚上發現各種error、bug相繼發生,因為更新幅度非常大,需要花滿多時間判斷問題發生在哪個部分。

next.js router bug

發現一個非常嚴重的問題,Safari點選網頁上的連結到外部網站,在返回頁面回來,next 會直接導引到error page。
( 到我發文這天都沒修復掉,持續有人回報。 )

next.js safari bug

next.js有個用法,建立_app.js,當作各個 pages/yourpath.js 共用的render point,我在這邊處理不同路徑共用title tag,_app.js需要依靠 pages/path.js 傳入資料,我就使用了getInitialProps 來處理server side call api取得的資料。

但是問題發生在 Safari 返回頁面,會使用之前的cache,並且不對server做請求,返回頁面會執行 getInitialProps 但是取不到 server side拿到的資料,所以資料會錯誤,導致錯誤發生。

目前看起來問題還在,這邊修復方法是,直接拉掉getInitialProps取server side資料,改到內層去render title。

react server、client side HTML 不同步

這是react 16再處理server side 到 client side render畫面的邏輯修改,為了增加render效能,react拋棄的比對server side to client html比對,官方建議server side 跟 client side的html要盡量保持一致。如果要有不一樣的話,建議在componentDidMount setState處理畫面更新。

發現部分的html畫卡在server side render layout,修復方法就利用server side 跟client side用不同的key值,讓react比對node做更新。但是如果要更新dangerouslySetInnerHTML用key方法也沒用,目前hotfix作法是兩邊用不同的html tag強更新,之後會改為componentDisMount更新。

react 16 官方宣告

In general, we don’t recommend that you render different content on the client versus the server, but it can be useful in some cases (e.g. timestamps).
However, it’s dangerous to have missing nodes on the server render as this might cause sibling nodes to be created with incorrect attributes.

Better server-side rendering

心得

更新大概花了2週左右時間,大部分時間都在調整next config,原先更新是為了使用react 16新語法,還有希望能加速專案build deploy的速度。結果next這部分是有稍快一點,但主要優點還是在於react語法,方便我們在開發上處理更多問題,還有跟上react更新腳步,未來希望能夠導入react hooks。

很多狀況在測試階段都沒有察覺,不幸的release後發現很多問題…,幸好都有找到原因修復掉。