美文网首页
ES6 学习笔记(18) Module 的加载实现

ES6 学习笔记(18) Module 的加载实现

作者: MrZhou_b216 | 来源:发表于2018-03-20 14:50 被阅读0次

1. 浏览器加载


  • 传统方法
    <script>标签打开deferasync属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。
    deferasync的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
  • 加载规则
    浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。
  <script type="module" src="./foo.js"></script>

浏览器对于带有type="module"<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。如果网页有多个<script type="module">,它们会按照在页面出现的顺序依次执行。
一旦使用了async属性,<script type="module">就不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。

对于外部的模块脚本(上例是foo.js),有几点需要注意。

代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
模块脚本自动采用严格模式,不管有没有声明use strict
模块之中,可以使用import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。
模块之中,顶层的this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的。
同一个模块如果加载多次,将只执行一次。

2. ES6 模块与 CommonJS 模块的差异


它们有两个重大差异。

CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

3. Node 加载


Node 对 ES6 模块的处理比较麻烦,因为它有自己的 CommonJS 模块格式,与 ES6 模块格式是不兼容的。目前的解决方案是,将两者分开,ES6 模块和 CommonJS 采用各自的加载方案。

Node 要求 ES6 模块采用.mjs后缀文件名。也就是说,只要脚本文件里面使用import或者export命令,那么就必须采用.mjs后缀名。require命令不能加载.mjs文件,会报错,只有import命令才可以加载.mjs文件。反过来,.mjs文件里面也不能使用require命令,必须使用import

目前,这项功能还在试验阶段。安装 Node v8.5.0 或以上版本,要用--experimental-modules参数才能打开该功能。
目前,Node 的import命令只支持加载本地模块(file:协议),不支持加载远程模块。

  • 内部变量

ES6 模块应该是通用的,同一个模块不用修改,就可以用在浏览器环境和服务器环境。为了达到这个目标,Node 规定 ES6 模块之中不能使用 CommonJS 模块的特有的一些内部变量。

首先,就是this关键字。ES6 模块之中,顶层的this指向undefined;CommonJS 模块的顶层this指向当前模块,这是两者的一个重大差异。

其次,以下这些顶层变量在 ES6 模块之中都是不存在的。

arguments
require
module
exports
__filename
__dirname

4. 循环加载

“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。

相关文章

  • ES6 学习笔记(18) Module 的加载实现

    1. 浏览器加载 传统方法 标签打开defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始...

  • babel 按需加载插件的实现

    实现按需加载 babel 插件根据 AST 分析 import 语法对 ES6 Module import 语法进...

  • ES6 module加载原理探究

    想起这个问题是源于阅读的es6手册时见到“Module 的加载实现”:http://es6.ruanyifeng....

  • Redis Module实现

    Redis Module实现 加载 卸载

  • 【ES6】Module的语法、加载实现

    概述 在ES6之前,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,...

  • ES模块语法学习小记

    原文:http://es6.ruanyifeng.com/#docs/module ES6模块是静态加载的(编译时...

  • ESM和CJS区别

    ES6 Module和CommonJS区别 区别一 前者属于编译时加载,即静态加载,在编译时就能够确定模块的依赖关...

  • Module的加载实现

    上面代码中, 标签打开defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,...

  • Module的加载实现

    浏览器加载 标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染...

  • Module 的加载实现

    本章介绍如何在浏览器和 Node 之中加载 ES6模块,以及实际开发中经常遇到的一些问题(比如循环加载) 一、浏览...

网友评论

      本文标题:ES6 学习笔记(18) Module 的加载实现

      本文链接:https://www.haomeiwen.com/subject/ococqftx.html