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

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

產生 BUILD_ID

發現 run 起來會抓不到 app.js,發現需要處理路徑問題,舊版 next build 出來的目錄,不會帶有 BUILDID,只會在編譯的時候,拿取.next 的 BUILDID 來當作路徑,之前是利用 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 後發現很多問題…,幸好都有找到原因修復掉。