原文:《关于 Nginx 和 Nuxt 结合这一事》最近终于用Nuxt重构了自己的博客。作为一个和Nuxt一起生活了一个月的强者,我可以说这个框架是的:SSR的解决方案非常巧妙,难度也不大。记住它的生命周期后,你可以根据官方文档快速上手。有SEO需求的可以试试一波,不过nuxt在前后端对接和最终部署的时候还是有很多坑,而且还挺大的。这里我列出两个我认为比较难的问题。Nuxt默认将URL/XX映射到目录/static/XX,不能修改一些客户端和服务端共享的请求。如何封装一个请求方法,使得客户端在客户端的时候,请求中携带请求头,在服务中直接发送到后端(比如首屏渲染),参数如来自客户端的请求标头或IP被传递到后端。我称它们为资源映射和请求交付问题。不知道其他人有没有被这个困扰。卡了好久了。将这两个问题的解决方法记录在这里,希望对有需要的人有所帮助。注:为简化描述,下文将Nuxt服务器简称为“server”,php后端简称为“backend”。二服务请求传递问题解决这个问题,最好认真考虑浏览器发起的请求是如何在服务器中反复跳转的。假设nuxt服务器工作在8080端口,后端(这里以php为例)工作在9000端口。理想情况下(不考虑静态资源请求)如下图,相同颜色的线是一对请求和回应。对应代码,图中③和⑤可能会请求同一个接口(比如asyncData中的请求)。一个是nuxtserver(请求头基本为空,IP为本机IP)。前者很好地满足了要求,但后者是一个大问题,后端丢失了客户端的信息。所以这里的重点是“转原请求”,即将③的请求头和IP替换成②的请求头和IP请求头。对于请求头的传递,可以利用context.req的特性:在客户端运行时,req是undefine;服务器运行时,req是nodejs的Request对象,里面包含了请求②的信息,req.headers是它的请求头。有了这个特性,就可以根据req是否undefine来判断是否在server端。只有在服务端的时候才需要用原来的请求头覆盖当前的请求头。下面是实现代码,扔到plugins中注册注入到两端importaxiosfrom'axios';importqsfrom'qs';axios.defaults.timeout=10000;axios.defaults.withCredentials=true;exportdefault({app,req},inject)=>{//封装get方法inject('fetch',(url,params={},req=null)=>{returnnewPromise((resolve,reject)=>{axios.get(url,{params:params,headers:req?req.headers:{}}).then(response=>{resolve(response)}).catch(err=>{reject(err)})})});//封装post方法inject('post',(url,data={},req=null)=>{returnnewPromise((resolve,reject)=>{axios.post(url,qs.stringify(data),{headers:{'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8',...(req?req.headers:{})}}).then(响应=>{resolve(response)}).catch(err=>{reject(err)})})});}在使用的??时候,只要涉及到服务器的请求都必须在req中传入,比如this.$fetch('114514.php',{},req);而只涉及客户端的请求可以省略req参数,例如this.$post('114514.php',{})IP转IP请求的IP本来就不保存在请求头中,php获取到的IP只识别TCP连接的IP,所以为了传输IP,需要开一个新字段给Store,让后台从这个新字段中获取客户端的IPNginx。有一个现成的proxy_set_header命令可以帮助我们在反向代理时修改请求头。如果有更多的需求,我们甚至可以设置更多的上游nuxtserver{server127.0.0.1:8080;keepalive64;}server{#...location/{proxy_redirectoff;proxy_set_header主机$host;#把客户端的IPproxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;proxy_read_timeout1m;proxy_connect_timeout1m;proxy_passhttp://nuxtserver;#...}这些新增加的字段最终会出现在客户端的req.headers中,然后使用上面请求头传递的方法,IP等信息就可以传递给后端了(比如php可以传递$_SERVER['HTTP_X_REAL_IP']获取设置的IP)映射问题URL指向通常分为三种:页面、静态资源、后端接口。nuxt最大的问题是它会把pages以外的类型映射到/XX到目录/static/XX。最简单的解决办法就是把所有的资源文件和接口文件都扔到static文件夹下,但是这样会很不协调,因为没有以static开头的接口路径。目前比较有效的方法是在nginx配置文件中写规则进行拦截。一旦判断该URL是在请求资源,就会被nginx全部映射到对应的目录或者禁止访问。givenuxtserver{#...#禁止文件(文件夹)位置^~/node_modules{return404;}#静态资源位置~^/(downloads|music|site|static|tmp|uploads)/{roothtml;7天到期;}#PHPCGI位置~\.php${roothtml;fastcgi_pass127.0.0.1:9000;fastcgi_indexindex.php;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;包括fastcgi_params;主机$主机;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;proxy_read_timeout1m;proxy_connect_timeout1m;proxy_passhttp://nuxtserver;}#...}_这是记录的结尾。如果有dalao有优化建议或者新方案欢迎讨论
