2017 年,你还在用 JSONP 吗?

2017-04-04 19:43:59 +08:00
 eric6356

太长不看

JSONP 就是个 dirty hack ,吃枣药丸,能不碰就不碰。不服来辩!

细节

即将接手一个前端项目。
这项目之前是用 Rails + Angular1 做的,现在我们打算把 Rails 干掉,所有数据都让前端直接从 api.example.com 取。
后端 api.example.com 一定是我们自己 serve ,但前端的话:

  1. 可能部署 NGINX 到各个客户服的务器上
  2. 也可能是我们自己的 admin.example.com
  3. 当然更有可能同时会有好几套,这还不确定

之前的思路是,前端判断一下其所处的环境是否支持 CORS ,不行的话用 JSONP 当做 fallback 。至于 GET 以外的请求,这边用 JSONP 模拟了一套实现,看起来相当完善,前后端都有支持。并且我们的请求都很小,似乎不用考虑 413 的问题。

而现在我个人的想法是,无论部署在哪,都让跑这个项目的那个 NGINX 做一次 proxy_pass ,反代到 api.example.com (对应 1 ),或是反代到我们私有网络跑 api 的那台机器上(对应 2 )。这样的优点至少有:

  1. 跨域这件事情根本不存在了,也不用去考虑 CORS 的各种坑
  2. 客户方面,只需要跑 NGINX 的那台机器连得到 api.example.com 就行,跑浏览器的机器可以是纯内网环境

缺点:

  1. 多了一次代理转发,做反代的机器机器会有额外性能开销(如果和 api 不是同一个 NGINX 的话)
  2. 本来前端所有的文件可以都交给 CDN ,现在则必须要一台服务器了

总之在我印象中,JSONP 这玩意就是落后于时代(亦或是超前于时代)的一个 hack 。以前、现在、未来都未曾、没有、不会出现在 W3C 或是 RFC 标准中,应该被抵制才对。

我目前还没有说服团队成员放弃 JSONP ,尤其是用 JSONP 模拟实现了一整套非 GET 请求的前辈。
请各位 dalao 赐教。

4688 次点击
所在节点    前端开发
28 条回复
nfroot
2017-04-04 20:28:39 +08:00
放弃没问题啊。

少数赞成多数好不好 0 0
imswing
2017-04-04 20:30:19 +08:00
origin allows *
gdtv
2017-04-04 20:30:45 +08:00
存在却合理,既然有简单的方法解决问题(虽然这个方法不标准),为何还要用复杂的方法呢(你说的 proxy_pass 的方法我觉得比 jsonp 复杂、麻烦很多很多)?
eric6356
2017-04-04 20:42:30 +08:00
@imswing
CORS 会有一些坑,比如某些企业防火墙会屏蔽 OPTIONS 请求。这我们希望尽量避免,或者至少有 fallback 。
eric6356
2017-04-04 20:48:02 +08:00
@gdtv 也就 nginx 加一行配置?
相反 jsonp 的话,因为我很可能要完全重写这个项目,所以我需要按照目前这个并不标准的方案重新实现 JSONP 模拟非 GET 请求。当然写得好的话可能也就几十行代码,或许也是一种锻炼。
nfroot
2017-04-04 21:04:43 +08:00
“之前的思路是,前端判断一下其所处的环境是否支持 CORS ,不行的话用 JSONP 当做 fallback ”

楼主请问一下,你有更好的办法么
eric6356
2017-04-04 21:20:33 +08:00
@nfroot 我说了用 NGINX 做 proxy_pass ,当然如果如果把解决方式限定在浏览器端的话的话我也就没有更好的办法了。
我是认为反代一下之后,前后端的代码都可以更简单。
des
2017-04-04 21:31:43 +08:00
iframe 嵌入,然后用 postMessage 去获取怎么样?
刚刚想到的
eric6356
2017-04-04 21:46:47 +08:00
@des 能详细说一下吗?
是不是需要让 api.example.com 的某个接口返回某个 html ,其中有个 script 从 api 取数据,并且给 window 注册 message 事件并且在响应函数里调用 event.source.postMessage 发数据回来。
听起来麻烦得很,而且让 api 返回 html 页面真的好么?
des
2017-04-04 21:56:21 +08:00
@eric6356 所以还是 CORS 好弄,实在不行用 flash 也行。。。
SoloCompany
2017-04-04 22:01:25 +08:00
标题党

你说的“技术”有哪一样是在 2016 才出现的?👎
jianyunet
2017-04-04 22:12:27 +08:00
这种情况很常见,我的选择方式通常是,如果那个 jsonp 的模拟是开源项目而且比较健康的话,就可以用,如果是需要自己造轮子的话就尽量避免
otakustay
2017-04-04 22:38:36 +08:00
我不太理解 jsonp 这种几乎没有副作用的东西为什么就是能不碰就不碰了,不碰对你来说到底有什么好处了……
另外用 nginx 做反代最大的问题难道不是丢 cookie 么?
undeflife
2017-04-04 22:50:56 +08:00
也许是我没看明白,你这场景有点混乱,而场景都还没确定,先揪这么个细节是不是太早期?

>>这项目之前是用 Rails + Angular1 做的,现在我们打算把 Rails 干掉,所有数据都让前端直接从 api.example.com 取。
那你们另外有后端咯 那这个 rails 的作用是啥 - -#

>>可能部署 NGINX 到各个客户服的务器上
你们的前端代码还需要部署到客户内网 客户机还可能是纯内网环境?

>>本来前端所有的文件可以都交给 CDN ,现在则必须要一台服务器了
客户机有纯内网环境了,前端文件怎么能全部交给 cdn? 不是还是至少需要个能外网的机器反代吗?既然反代 server 是必要的,多加一个 api 的反代有什么问题?
eric6356
2017-04-04 22:50:59 +08:00
不碰的理由:
1. 不符合任何标准,应该抵制(个人感情因素)
2. 你也说了「几乎」没有副作用
丢 cookie 我确实没有考虑过,感谢指出。
不过一个 RESTful 的 API ,真的需要 cookie 吗?
eric6356
2017-04-04 22:51:31 +08:00
@otakustay
楼上 #15
otakustay
2017-04-04 22:57:11 +08:00
我承认如果 cors 完全可用的情况下 jsonp 并不合适,但问题就在 cors 并不完全可用,而且同样会有一定的负面影响,比如你用非 GET 的请求就会用 preflight OPTIONS request 浪费时间,你用反向代理就给自己的服务增加压力(你想想日 PV 有 3000W 的时候你什么感觉)
这样比起来, jsonp 的副作用比 cors 小多了啊,一个函数封装以后就完全无感知了, jsonp 真正的缺点是全 GET 在安全性上守不住
eric6356
2017-04-04 23:00:07 +08:00
@undeflife 首先感谢仔细看了这个帖子
1. 之前一些数据是靠 Rails 查库的,另一些是 JSONP 。
2. 一个应用可以卖给很多客户。卖给谁,怎么卖,现在应用没有开发完,自然是不确定的了咯。
3. 抱歉这里确实没写清楚,我在目前考虑各种场景,企图用一个方案满足所有需求。

而且你说的很对,场景没定的话很多考虑都是多余的。
eric6356
2017-04-04 23:32:26 +08:00
@otakustay 其实我并不太明白反代到底会有多大的额外开销。
画了张图

A 和 B 是 example.com 自己 serve , C 和 D 是让客户 serve 。
那么 A 和 B 相比,以及 C 和 D 相比,我们 example 这一侧的其实并没有什么区别吧?
eric6356
2017-04-04 23:41:56 +08:00
@undeflife
#19 图 C 就是我考虑的,前端项目可以只用 CND 的情况

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/352477

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX