聊一聊原生浏览器中的模块

互联网人学习成长社群

第五期Web全栈架构师火爆报名中~

自从ES2015定稿以来,我们通过 Babel 等转换工具可以在项目中直接使用【模块】。前端模块化开发已经是不可逆转,在 ECMAScript module 之前我们通过 requirejs、seajs、LABjs,甚至最早的时候我们通过闭包来实现模块化开发。

目前一些主流的的浏览器厂商已经在他们新版的浏览器中原生支持了【模块】,今天我们就来原生浏览器中的模块到底如何。

目前原生支持模块用法的浏览器有:

Safari 10.1

Chrome 61

Firefox 60

Edge 16

要使用原生浏览器的模块,你只需要在 script 标签上添加一个 type=module 属性, 浏览器就会把这个脚本(内联脚本或者外联脚本)当作模块来处理。

默认延迟加载

当网络状况不好的时候,脚本加载会阻塞浏览器解析 HTML。通常我们可以通过在 script 标签上使用 defer 属性来解决阻塞问题,但是这也会造成脚本只有在文档解析完成后才执行,同时还要兼顾其他延迟脚本的执行顺序。默认情况下模块脚本的表现类似于 defer — 它不会阻塞 HTML 的解析。

模块脚本的执行队列与使用了 defer 的常规脚本一致。

内联模块也是延迟加载的

唱过脚本会忽略 defer 然而内联模块总是 defer 的,不管它是否引入了东西。

内联/外联 模块都支持异步加载

在普通脚本中,async 能让脚本的下载不阻塞HTML的解析并在下载完成后尽快执行。和普通脚本不同,内联模块脚本支持异步加载的。

同样的,异步加载的模块可能不会按照它们在DOM中出现的顺序执行。

模块只执行一次

如果你使用过ES6的模块, 那么你肯定知道你可以多次引入同一模块但是他们只会执行一次。在Html中也一样, 一个URL模块脚本在一个页面中只会执行一次。

遵循 CORS

不同于普通脚本,跨站引用模块脚本(及其引入)需要遵循CORS。 这意味着跨源模块脚本必须返回有效的CORS头,例如Access-Control-Allow-Origin:*。

不需要凭证

针对同源请求,大部分基于CORS的API需要请求带上凭证(如:cookie),但是 fetch()和模块脚本是个例外,他们默认不会带上相关凭证除非你明确指定。

如果你想在同源请求模块脚本时带上凭证,可以设置 crossorigin 属性。如果跨站请求也想带上的话,可以设置 crossorigin="use-credentials",需要注意的是跨站的站点需要在请求返回头中加上 Access-Control-Allow-Credentials: true。

这里还有一个关于 模块只执行一次 的坑。当你通过一个URL引入一个模块时,如果一开始你以无凭证的方式请求,然后又以有凭证的方式再请求一次,你得到的返回都是无凭证请求的那次。这就是我为什么会在第二次请求时在URL后加上?,用于区分两次请求。

更新:以上可能很快会改变。 默认情况下,fetch()和模块脚本都会向相同来源的URL发送凭据。

Mime-types

与普通脚本不同,模块脚本必须提供有效的JavaScript MIME类型,否则它们将不会执行。 HTML标准建议使用 text/javascript 。

有你想看的精彩

感谢您的阅读,如果你觉得我的公众号还不错,请多帮我推荐给你的朋友,多谢了。

前端大牛爱好者:每天一篇前端技术文章,不定时前端干货发送

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180708B16XOE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券