专栏首页前端之旅file 协议导致的跨域问题以及解决方案

file 协议导致的跨域问题以及解决方案

问题复现: 学习 ES6 模块化的时候,写了这段代码:

<script src="./aaa.js" type="module"></script>
<script src="./bbb.js" type="module"></script>
<script src="./aaa2.js" type="module"></script>

结果跑到 chrome 下面一看,报错了:

看起来是跨域问题,也就是只支持 httphttps 等这种类型的跨域请求,不支持 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 必须合法 —— 也就是必须带有 httphttps 等,以用来表明请求源。

但是别忘了,我们现在是在本地打开文件,使用的不是 http 协议,而是 file 协议,它根本就没有跨域请求需要的 origin(注意看上图,origin 是空的)。所以,这种情况就要报错了。其实从报错信息中也能读出这一点。

那么,我们现在用 live server 在本地开启服务器,再看一下控制台:

可以看到,因为这次不是用 file 协议访问了,所以一切正常。

参考: Understanding ES6 Modules ES6 module support in Chrome 62/Chrome Canary 64, does not work locally, CORS error Access to Image from origin ‘null’ has been blocked by CORS policy

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ES6 参数默认值引起的中间作用域

    ES6 参数默认值的问题,其实之前在这篇文章中已经有涉及,之所以再谈起这个问题,是在阅读《ES6 标准入门》时产生的一个疑惑。阮老师的代码是:

    Chor
  • Vue 生命周期与钩子函数

    Vue 的生命周期共有 8 个阶段,即创建前/后, 载入前/后,更新前/后,销毁前/销毁后,并对应地有很多钩子函数,让我们在控制整个Vue实例的过程时更容易形成...

    Chor
  • 解析赋值、浅拷贝和深拷贝

    浅拷贝即 swallow copy,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型...

    Chor
  • 那些延时加载图片的开源插件

    图片延时加载技术对大流量的网站来说是十分实用的。目前图片在网站中大量使用,如果不加处理的话会对服务器和带宽造成级大压力,通过只渲染当前用户可见区域的图片,可以极...

    疯狂的技术宅
  • JavaScript的引入方式和基本属性

    2、引入外部js文件:通过 src 引入,此时 script 标签内添加任何js代码都不起效果。

    德顺
  • React之你的第一个React程序

    1、声明式设计 2、高效:通过对DOM的模拟,最大限度的减少与DOM的交互。 3、灵活:可以与已知的框架或库很好的配合。 4、JSX:是js语法的扩展,不一定使...

    用户1272076
  • OpenCV计算物体的重心坐标(2值图像)

    http://download.csdn.net/detail/wangyaninglm/9389338 

    用户1539362
  • selenium的一些js操作

    3.这里可以修改scrollTop 的值,来定位右侧滚动条的位置,0是最上面,10000是最底部。

    周小董
  • python自动化17-JS处理滚动条

        selenium并不是万能的,有时候页面上操作无法实现的,这时候就需要借助JS来完成了。

    用户2398817
  • 基础学习python

    判断输入数字是否符合“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问几何?”

    adventureisoutthere

扫码关注云+社区

领取腾讯云代金券