这篇文章上次修改于 2 个月前,可能其部分内容已经发生变化,如有疑问可询问作者。

背景

现在很多网站都使用了前后端的分离的架构,前后端可以不在一台服务器上,前端为了保证 SEO,必须使用预渲染,SSG 或 SSR 技术。而我的站点则使用了 NextJS 的 SSR 技术。在渲染端预渲染页面时首先会调用 Axios 实例去请求接口。但是有一个问题。在渲染端请求的头部永远是渲染端本身的 User-Agent 和 IP,并不能获取到用户本身的元数据。显然这并不是我们先要期望得到的结果。当然这个情况只发生在首次访问。
为了解决这种问题,必须想办法把原本的请求头部或者其他元数据转发到此次请求上。有点类似反向代理,但是又有点不同。好在 NextJS 为我们提供了这一接口。

踩坑之路

带着这个想法,我踩了很多坑。
首先我查到 NextJS 可以在 Custom App 上定义 getInitialProps (和 NextPage 一致)。但是它接受一个参数,类型为 AppContext 位于 next/app 包中。
getInitialProps 必须返回一个对象,但是因为他是 Root Component。必须接受所有 Children props,然后返回。好在 NextJS 为我们提供了一个方法,我们只需要如下操作就能完成建基。
之后我们需要进行扩展。
首先我们要知道 props 上有一个 ctx 的对象,ctx 中有一个 req 对象,类型为 IncomingMessage。这个 req 对象就是用户的请求,我们只需要把这个 req中的某些元数据附加到之后请求的 axios 实例上即可。当然只需要判断是不是在预渲染的时候就行了,因为如果不在渲染端就不需要做转发。
我们可以使用 typeof window === 'undefined' 来判断是否在渲染端。
之后就是怎么获取到用户的真实 IP 了,如果使用了 Nginx 或者其他服务器软件进行反代,一般会把真实 IP 附加到 Headers 上。
之后就是怎么附加到 Axios 上。这里有一个坑,不要直接附加到 Axios.default.headers 上,因为这样看似可以(的确只在 dev 环境可以),但是 production 立马暴毙,血的教训
我们可以附加到 Axios 实例上。直接在 service.default.headers.common 上对键进行赋值即可。
而获取 UA 就简单了,直接 request.headers['user-agent'] 就能拿到。
以上就是完整的代码了。

亲亲留个评论再走呗

正在加载评论区...