file 协议导致的跨域问题以及解决方案
source link: https://www.tuicool.com/articles/7N3QFvF
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
问题复现:
学习 ES6 模块化的时候,写了这段代码:
<script src="./aaa.js" type="module"></script> <script src="./bbb.js" type="module"></script> <script src="./aaa2.js" type="module"></script>
结果跑到 chrome 下面一看,报错了:
看起来是跨域问题,也就是只支持 http
, https
等这种类型的跨域请求,不支持 file
协议类型的(直接本地打开文件)。解决方案如下:
1.给 chrome 快捷方式添加参数:
–allow-file-access-from-files
实测无效。貌似还得重启电脑,太麻烦了,遂放弃。
2.换浏览器。经过测试,Edge 可以正常显示,但 FireFox 还是报跨域错误:
3.用 IDE。像 Webstrom 这类型的 IDE 是内置 http 服务器的,这样可以不通过 file
协议打开文件,不过这个还是有点麻烦,我没尝试。
4.使用热更新插件。刚好想起编辑器里安装了 live server 这个插件,这个其实是做同步刷新用的,但是由于它可以在本地开启一个服务器,所以可以利用这一点(localhost 访问)。尝试之后发现确实不报错了。
5.Node 开一个服务器
// server.js let express = require('express'); let app = express(); app.use(express.static(__dirname)); app.get('/',function (req,res) { res.send('./index.html',{root:__dirname}); }) app.listen(8203);
问题是解决了,但总觉得心里不踏实,所以开始了艰苦的 google 之旅,最后算是找到了问题的根源。但我还是想从同源策略开始解释:
同源策略(Same origin policy),是出于安全而诞生的一种约定,规定了只能在本域内进行资源访问。所谓同源是指”协议+域名+端口”三者相同。
不同源之间进行资源访问,就需要跨域。特殊地,有三个标签默认是允许跨域加载资源的:
<img src="xxx"> <link href="xxx"> <script src="xxx">
关键来了,ES6 使用模块的时候要在标签中声明 type="module"
,而这类 使用了模块的 script
是受限于同源策略的 。我们尝试改动之前的代码如下:
<script src="./aaa.js" type="module" defer="defer"></script> <script src="./bbb.js" type="module" defer="defer"></script> <script src="./ccc.js" type="text/javascript" defer="defer"></script>
可以看到,前面两个 script
使用了模块, Sec-Fetch-Mode
都是 cors
,而最后一个就是常规的引入脚本,不受同源策略影响,因此是 no-cors
。
我们可以理解为前两个 scirpt
发送了 Cors 跨域资源请求,而这种请求要求 request header 的 origin 必须合法 —— 也就是必须带有 http
, https
等,以用来表明请求源。
但是别忘了,我们现在是在本地打开文件,使用的不是 http
协议,而是 file
协议,它根本就没有跨域请求需要的 origin
(注意看上图, origin
是空的)。所以,这种情况就要报错了。其实从报错信息中也能读出这一点。
那么,我们现在用 live server 在本地开启服务器,再看一下控制台:
可以看到,因为这次不是用 file
协议访问了,所以一切正常。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK