还愿
在上一篇《Vue-cli 3.x + axios 跨域方案踩坑指北》中说到通过webpack配置proxy代理
来实现的跨域只是开发环境下的便利,真正上线时源代码被打包为静态资源是没有devServer
帮你转发请求的,那上文文末也立了个flag,说下次在谈到这个跨域问题尝试找找答案。最近在实习,通过和导师交流和自己理解,发现Node中间层是一个目前前后端分离开发模式下比较普遍的跨域解决方案,其实原理与proxy
差不多,无非是proxy
是devServer提拱好的,而Node中间层则需要我们自己实现一个proxy
,当然Node中间层的作用远远不止代理转发请求这么简单。在文末也会概述Node中间层为前端开发带来了哪些变化和机遇,本文大部分讲解如何使用Node中间层转发请求实现资源跨域访问。
抽象的理解
要明白Node层为什么能实现跨域,首先要明白一个原理:跨域问题是浏览器的同源策略的安全机制引起的,服务器之间是不存在跨域问题的,这也不是说服务器之间没有安全机制,只是服务器之间的调用无论是通过http访问还是通过rpc调用都是协议层面的机制,并没有限制必须同源。这也就是Node层跨域的实质,我们把静态文件和Node中间层放在同一个域下,这样前端资源和Node层的通信不会受同源策略影响,然后我们通过Node中间层把前端的资源请求转发到真实的请求地址,在通过中间层把请求返回的数据传给前端,这样就实现了此域跨彼域的串门操作。
具体操作
按理说,是可以使用一些中间件来做这个代理转发的,不过目前还没有研究,以后研究到再写文章记录。我们这次的Demo,使用的是Node的原始API(http.get API做get请求访问真实资源地址) + express中间件(做服务器使用),前端异步调用还秉承上篇文章的axios。
假设,我们前端这样异步访问一个地址:
this.axios.get('/api/index').then(res=>{...})
express服务可以这样写:
app.get('/api/index',(req,res)=>{
//请求远程地址的API
getHttp().then(data=>{
console.log(data);
res.send(data);
}).catch(err=>{
res.send(err);
})
//返回数据给前端
})
其中getHttp()
是封装的一个promise
,这个promise
的作用就是转发请求并在成功后以data(请求到的数据)回调resolve函数。然后,在成功请求后,在then
的第一个回调参数中将数据在传递给前端
const getHttp = ()=>{
return new Promise((resolve,reject)=>{
http.get('http://localhost:8080/New/Index', (res) => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('请求失败\n' +
`状态码: ${statusCode}`);
}
if (error) {
console.error(error.message);
// 消费响应数据来释放内存。
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`出现错误: ${e.message}`);
});
})
}
这样就实现了一个简单的跨域demo的框架结构。
最后,谈谈Node层对前端的影响
Node让给我们前端er的能力开始向服务端扩张,当然要说对抗老后端Java,Node还是略显单薄。但是各有各的好处,大体上来说,业界普遍认识是Node一般用来做中小型Web应用开发或者在大型应用开发中充当中间层的作用。那我们就来谈谈这个中间层有什么意义?
- BFF架构 (backend for frontend) 在RESTFul接口的架构中,后端接口众多,规范不统一,而且后端API返回的数据大部分需要做二次处理,引入Node层后就可以为前端提供统一规范的接口,而且可以将数据二次处理放到Node层处理,前端则专注于UI逻辑的构建 ,我们习惯称这个叫BFF
- 预渲染,前端渲染有一个最大的问题就是首屏白屏加载时间会比较长,影响用户体验。这个问题出现的本质是JS客户端渲染的性能问题,遇到较大的计算量较大的JS处理,会阻塞UI绘制导致JS不执行完无法加载DOM的问题,一个很好的解决方案就是预渲染。预渲染可以在Node层做模板渲染(相当于中间层的服务器渲染),这样可以有效解决白屏问题。那为什么不直接用服务器端渲染,是因为考虑到前后端分离开发的便利。
- 控制路由,进一步分离UI与逻辑,前端渲染中路由是前端控制的,Node层的引入可以把路由控制权转让给Node,这样前端更加专注于UI,复杂的事情交给Node去做,即高效有关注分离,提高维护性。
希望,我的一点探索可以对你有用,这也是我分享的初衷。感谢支持!