Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript Module Standard Before ES6 #16

Open
KKKyrie opened this issue Feb 9, 2020 · 0 comments
Open

JavaScript Module Standard Before ES6 #16

KKKyrie opened this issue Feb 9, 2020 · 0 comments

Comments

@KKKyrie
Copy link
Owner

@KKKyrie KKKyrie commented Feb 9, 2020

JavaScript 的模块化“升级”之路可以理解为一个“倒逼产出”的过程。
在很久以前,JavaScript 的职责范围仅限于在浏览器端做表单校验和简单的交互动画,以至于经常被其他语言的爱好者看不起,更不用提什么模块化了,那怎么引入代码呢?一个 script 标签足矣

Node 将模块带入 JavaScript 世界

到了 2009 年,美国的天才工程师 Ryan Dahl 创造了 Node.js,让 JavaScript 具有了服务端编程的能力。在那个年代,浏览器侧的应用复杂度偏低,即便没有模块也没有什么大碍,但到了服务端,模块系统是一门后端语言的必备能力,在与操作系统和其他应用互动时,一定要有模块。

CommonJS

Node 的模块系统,就是参照 CommonJS 规范实现的。
CommonJS 的规范比较简单,涉及三个概念:模块引用、模块定义和模块标示。

模块引用

在规范中,存在 require 方法,这个方法接受一个参数,即模块标示,以此为依据引入一个模块的 API 到当前的 context 中。

const api = require('api')

模块定义

对应 require 方法,每一个模块的 context 提供了 exports 对象用于导出导出当前模块的方法和变量,并且它是唯一导出的出口。在每一个模块中,还存在一个 module 对象,它代表模块自身,而 exportsmodule 的属性。在 Node 中,一个文件就是一个模块

exports.fetchUserInfo = function() {
  console.log('fetch!');
}

模块标示

模块标示就是传递给 require 方法的参数,它必须满足以下三个条件中的某一项:

  1. 符合小驼峰命名的字符
  2. ... 开头的相对路径
  3. 绝对路径

在 Node 中,模块标示可以不写文件名后缀 .js

AMD

在 Node 的疯狂普及之后,人们自然想把 CommonJS 的实现照搬到浏览器中,但是有一个明显的问题:同步阻塞。对于服务端来说,同步读取模块是一件比较简单的事情,毕竟文件都存放在本地硬盘。但来到浏览器端,由于网速的影响,加载一个模块可能会耗费很长的时间,浏览器就会“假死”在那里。
于是就有了 AMD(Asynchronous Module Definition),异步模块定义。
在定义模块的写法上,AMD 要比 CommonJS 复杂一些,但同时也兼容了 CommonJS 的写法:

// define(moduleId?: string, depends: string[], callback: function)
// pwd: apiModule.js
define('api', ['packages/api'], function(api){
  function fetchUserInfo() {
    api.fetchUserInfo();
  }
 
 return { fetchUserInfo };
})

有了异步这个词,不难想到回调函数,事实也确实如此:在将模块引入后,具体使用它们的代码都被包裹在一个回调函数中:

require(['apiModule'], function(api) {
  api.fetchUserInfo();
});

CMD

在有了 AMD 后,聪明的前端人发现,AMD 还是有可以提升的空间的,最主要的一个原因是,AMD 加载模块的方式是提前加载所有模块,无法做到按需加载,在很多场景下,这对前端资源都是一种不小的浪费。
于是就有了 CMD(Common Module definition),通用模块定义。
明显超越 AMD 的一点是,它支持按需加载,即,用到的时候才去 require:

define(function(require, exports, module) {
  // 省略 100 行
  const $ = require('jquery');
  const el = $('#element');
  // 省略 100 行
  const api = require('api');
  api.fetchUserInfo();
});
@KKKyrie KKKyrie changed the title JavaScript Module Standard JavaScript Module Standard Before ES6 Feb 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.