Next.js項(xiàng)目實(shí)戰(zhàn)踩坑指南(筆記)
前言
github: https://github.com/code-coder/next-mobile-complete-app
已經(jīng)用Next.js快兩個(gè)月了,項(xiàng)目已經(jīng)提測(cè)了,這里總結(jié)一下開發(fā)過(guò)程中,以及在部署的時(shí)候遇到一些棘手的問(wèn)題。
疑難雜癥
1. 移動(dòng)端overflow:auto,ios滾動(dòng)卡頓
解決方案: 主容器增加樣式-webkit-overflow-scrolling: touch;
2. dev mode路由跳轉(zhuǎn)后樣式丟失
原因:dev下樣式根據(jù)頁(yè)面動(dòng)態(tài)加載,瀏覽器緩存文件styles.chunk.css造成樣式不更新。
解決方案: 利用版本號(hào)強(qiáng)制重載樣式文件
示例1:
// 在Layout組件中 <Head> <title>{title}</title> {process.env.NODE_ENV !== 'production' && (<link rel="stylesheet" type="text/css" href={'/_next/static/css/styles.chunk.css?v=' + Router.route} />)} </Head>
示例2:
// 在_app.js中 import Router from 'next/router'; Router.events.on('routeChangeComplete', () => { if (process.env.NODE_ENV !== 'production') { const els = document.querySelectorAll('link[href*="/_next/static/css/styles.chunk.css"]'); const timestamp = new Date().valueOf(); els[0].href = '/_next/static/css/styles.chunk.css?v=' + timestamp; } });
3、Android 鍵盤彈起窗口會(huì)變小,有 flex 或者 position 是 absolute 或者 fixed 布局會(huì)變
這里直接把body.height設(shè)置為瀏覽器的窗口高度。
doc.body.style.height = docEl.clientHeight + 'px';
4、跨域及傳遞cookie的問(wèn)題
第一步,登錄成功后api服務(wù)器返回cookie。
跨域訪問(wèn)要接收cookie,解決辦法也很簡(jiǎn)單只需要API服務(wù)器根據(jù)請(qǐng)求地址設(shè)置Access-Control-Allow-Origin的值為請(qǐng)求地址的ip就可以了(測(cè)試環(huán)境可以動(dòng)態(tài)設(shè)置這個(gè)ip,生產(chǎn)可以設(shè)置指定的域名或者ip地址)。
第二步,瀏覽器自動(dòng)緩存,再后續(xù)請(qǐng)求中攜帶此cookie。
fetch或axois請(qǐng)求都默認(rèn)不帶cookie,需要通過(guò)option配置打開。
- fetch要配置`{ credentials: 'include', mode: 'cors' }`
- axois要配置`axios.defaults.withCredentials=true;`
另外,還可以通過(guò)服務(wù)器代理走內(nèi)網(wǎng)訪問(wèn)api。
以下為我們公司所采用的解決方案:
為了解決跨域以及部署不同服務(wù)器需要修改 api 地址的問(wèn)題,我們使用 前端服務(wù)器代理 + dns 解析。整個(gè)流程如下圖所示:
通過(guò)NODE_ENV環(huán)境變量來(lái)配置開發(fā)和生產(chǎn)的地址。
const isProd = process.env.NODE_ENV === 'production'; process.env.BACKEND_URL = isProd ? '/relative_url' : 'http://text.api.com'; process.env.BACKEND_URL_SERVER_SIDE = isProd ? 'http://bff.api.com' : 'https://prod.api.com'; module.exports = { 'process.env.BACKEND_URL': process.env.BACKEND_URL, // 客戶端渲染請(qǐng)求,是個(gè)相對(duì)地址,在前端服務(wù)器被代理到API服務(wù)器 'process.env.BACKEND_URL_SERVER_SIDE': process.env.BACKEND_URL_SERVER_SIDE // 服務(wù)端渲染請(qǐng)求,是API服務(wù)器地址,僅供內(nèi)網(wǎng)訪問(wèn) };
5、服務(wù)端渲染時(shí)帶 cookie 請(qǐng)求的問(wèn)題
這里用到一個(gè)插件叫nookies。
在_app.js中全局解析cookies注入ctx:
static async getInitialProps({ Component, ctx }) { let pageProps = {}; let cookies = {}; if (ctx.isServer) { cookies = parseCookies(ctx); } if (Component.getInitialProps) { pageProps = await Component.getInitialProps({ ctx, cookies }); } return { pageProps }; }
然后就可以通過(guò)頁(yè)面請(qǐng)求:
static async getInitialProps({ ctx }) { const { store, req, isServer, cookies } = ctx; store.dispatch(setNav({ navTitle: 'Home', isHome: true })); store.dispatch(getDataStart({ settings: { isServer, cookies } })); }
在proxyFetch
中就會(huì)根據(jù)isServer
的值來(lái)分辨是服務(wù)端API請(qǐng)求還是客戶端API請(qǐng)求。服務(wù)端請(qǐng)求會(huì)把cookies寫入Fetch的header中。
const prefix = isServer ? process.env.BACKEND_URL_SERVER_SIDE : process.env.BACKEND_URL; isServer && (this.headers['cookie'] = 'EGG_SESS=' + cookies['EGG_SESS'] + ';';) // fetch核心 fetch(prefix + url, { headers: this.headers, ...this.init, ...options })
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js實(shí)現(xiàn)彈出窗口、頁(yè)面變成灰色并不可操作的例子分享
為了更好的用戶體驗(yàn),現(xiàn)在網(wǎng)頁(yè)中好多地方都使用彈出層。比如提示登陸,掃描微信二維碼圖片,論壇下載彈出扣除積分提醒等。2014-05-05javaScript強(qiáng)制保留兩位小數(shù)的輸入數(shù)校驗(yàn)和小數(shù)保留問(wèn)題
這篇文章主要介紹了javaScript強(qiáng)制保留兩位小數(shù)的輸入數(shù)校驗(yàn)和小數(shù)保留問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05JavaScript中將number轉(zhuǎn)為string的5種方法
這篇文章主要給大家介紹了關(guān)于JavaScript中將number轉(zhuǎn)為string的5種方法,在JavaScript的值類型轉(zhuǎn)換中,最常發(fā)生的就是string與number這兩種類型值之間的相互轉(zhuǎn)換,需要的朋友可以參考下2023-07-07