项目实战坑攻略1.移动端overflow:auto,iosscrollingfreeze解决方法:在主容器添加style-webkit-overflow-scrolling:touch;2.dev模式路由跳转转出后样式丢失原因:dev下的样式是根据页面动态加载的,浏览器缓存文件styles.chunk.css,导致样式不更新。解决方案:使用版本号强制重载样式文件示例1://在Layout组件
{title}{process.env.NODE_ENV!=='production'&&(
)}示例2://在importRouter中来自_app.js中的“下一个/路由器”;Router.events.on('routeChangeComplete',()=>{if(process.env.NODE_ENV!=='production'){constels=document.querySelectorAll('link[href*="/_next/static/css/styles.chunk.css"]');consttimestamp=newDate().valueOf();els[0].href='/_next/static/css/styles.chunk.css?v='+timestamp;}});3.Android键盘的弹窗会变小,如果有flex或者position是absolute或者fixed,布局就会改变这里直接设置body.height为浏览器窗口高度。doc.body.style.height=docEl.clientHeight+'px';4、跨域和传递cookie的问题第一步,api服务器登录成功后返回cookie。跨域访问接收cookie,解决方法也很简单。只需要根据请求地址将API服务器的Access-Control-Allow-Origin的值设置为请求地址的ip即可(测试环境可以动态设置这个ip,生产环境可以设置指定域名或者IP地址)。第二步,浏览器自动缓存这个cookie,并在后续请求中携带。fetch或axois请求默认不携带cookie,需要通过option配置开启。-Fetch需要配置`{credentials:'include',mode:'cors'}`-Axois需要配置`axios.defaults.withCredentials=true;`另外,也可以通过服务器代理访问api内联网。以下是我们公司采用的解决方案:为了解决跨域修改api地址和部署不同服务器的问题,我们采用前端服务器代理+dns解析的方式。整个过程如下图所示:通过NODE_ENV环境变量配置开发和生产地址。在env-config.js中constisProd=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,//客户端渲染请求为一个相对地址。前端服务器代理到API服务器'process.env.BACKEND_URL_SERVER_SIDE':process.env.BACKEND_URL_SERVER_SIDE,//服务器渲染请求为API服务器地址,仅供内网访问'process.env.LOCATION_PREFIX':process.env.LOCATION_PREFIX};5、服务器端渲染时用cookies请求的问题这里使用了一个叫做nookies的插件。在_app.js中全局解析cookieInjectctx:staticasyncgetInitialProps({Component,ctx}){letpageProps={};让cookies={};如果(ctx.isServer){cookies=parseCookies(ctx);}if(Component.getInitialProps){pageProps=awaitComponent.getInitialProps({ctx,cookies});}返回{pageProps};然后就可以通过页面请求了:staticasyncgetInitialProps({ctx}){const{store,req,isServer,cookies}=ctx;store.dispatch(setNav({navTitle:'Home',isHome:true}));store.dispatch(getDataStart({settings:{isServer,cookies}}));}在proxyFetch中会根据isServer的值来区分是服务端API请求还是客户端API请求。服务器请求会将cookie写入Fetch的标头中。const前缀=isServer?process.env.BACKEND_URL_SERVER_SIDE:process.env.BACKEND_URL;isServer&&(this.headers['cookie']='EGG_SESS='+cookies['EGG_SESS']+';';)//获取核心fetch(prefix+url,{headers:this.headers,...this.init,...options})6.需要部署到域名下的二级目录下,比如:有些公司的www.example.com/project业务场景下:如果需要分享cookies等,需要将项目部署到域名的二级目录下。这时候需要修改配置文件next.config.js:module.exports=withSass({assetPrefix:process.env.NODE_ENV==='production'?'/project':''});这个配置文件是修改下在构建时指向的根目录地址。但是由于Next.js的路由根目录是pages,所以客户端路由跳转后,生成的window.location.href地址会忽略二级目录。例如:假设我们的服务器地址是http://www.example.com/project,然后在首页使用Router.push('/login')跳转到登录页面,浏览器会直接追加域名name+port生成http的地址://www.example.com/login。而我们实际的服务器地址是http://www.example.com/projec...,跳转刷新页面后会报404。这时候就需要用到next提供的as参数(Router.push的第二个参数,link标签的as属性)。二级目录的地址可以写在process.env中。每次使用路由都要加上as参数。这时可以封装Link组件和Router,减少冗余代码。CustomLink.js文件importReact,{Component}from'react';importLinkfrom'next/link';exportdefaultclassCustomLinkextendsComponent{render(){const{href,as:asHref,children,...props}=this.props;返回(
{children});}}