天天看点

javascript-模块发展史

作者:重庆源码时代

什么是模块?

所谓的模块话就是将一个系统拆分成各个独立的部分,每个部分实现一块功能,然后组合在一起形成系统。这样的有点如下:

  • 可维护
  • 可复用
  • 可组合

JavaScript 程序本来很小——在早期,它们大多被用来执行独立的脚本任务,在你的 web 页面需要的地方提供一定交互,所以一般不需要多大的脚本。过了几年,我们现在有了运行大量 JavaScript 脚本的复杂程序,还有一些被用在其他环境

javascript-模块发展史

有必要提供一种将 JavaScript 程序拆分为可按需导入的单独模块的机制,二这个机制就是模块的规范,从js早期到现在,产生了很多的模块规范。接下来一一介绍一下:

文件划分

一个js文件即一个模块,然后再该js文件下定义模块的数据方法。最终将各个模块一script的方式引入到index.html中

优缺点:

  • 一定程度上实现了模块划分。
  • 变量同名
  • 变量方法来源不清晰
  • 依赖关系不明确

命名空间

命名空间的出现就是为了文件划分中,全局变量的问题。其实就是将每个文件模块下分散的数据和方法用对象包装起来(对象的名字做到唯一唯一性就好),然后放再window上。

优缺点

  • 变量或者方法来源清晰了
  • 只要人们按照一定规范命名,可以避免变量同名危险。
  • 不太安全,变量并没有私有化。
  • 但是依赖关系还是有问题,也就是script的加载顺序

IIFE

基于上诉不安全的原因,后来人们又提出了一个IIFE(立即执行函数)的方式,因为IIFE一运行就形成了一个私有的作用域,外界是没办法访问这个作用域下的变量的。

优缺点:

  • 比命名空间更加安全
  • 依赖关系还是无法解决。

CommonJS 规范(服务端-node)

最早比较正式的一个模块规范,主要用于node中。module.exports导出, require导入。语法如下:

// commonjs规范           

特点如下:

  • 得到node的支持
  • 基于文件的,一个文件就是一个模块。
  • 加载模块是同步的

缺点如下:

  • CommonJS 的实现需要使用到node操作文件的api,所以它并不能运行再浏览器上
  • CommonJS 本身约定以同步的方式进行模块加载,这种加载机制放在服务端是没问题的,一来模块都在本地,不需要进行网络 IO,二来只有服务启动时才会加载模块,而服务通常启动后会一直运行,所以对服务的性能并没有太大的影响。但如果这种加载机制放到浏览器端,会带来明显的性能问题。它会产生大量同步的模块请求,浏览器要等待响应返回后才能继续解析模块。也就是说,模块请求会造成浏览器 JS 解析过程的阻塞,导致页面加载速度缓慢。

AMD 规范

总之,CommonJS 是一个不太适合在浏览器中运行的模块规范,随后才又了AMD全称为Asynchronous Module Definition,即异步模块定义规范。模块根据这个规范,在浏览器环境中会被异步加载,而不会像 CommonJS 规范进行同步加载,也就不会产生同步请求导致的浏览器解析过程阻塞的问题了。

  • 使用define定义一个模块
// main.js
define(["./print"], function (printModule) {
  printModule.print("main");
});

// print.js
define(function () {
  return {
    print: function (msg) {
      console.log("print " + msg);
    },
  };
});           
  • 使用require 加载一个模块
// module-a.js
require(["./print.js"], function (printModule) {
  printModule.print("module-a");
});           

AMD规范并没有得到浏览器的支持,如果要再项目中使用,需要借助第三方的 loader 来实现,也就是require.js库。例子如下:

总结:

  • AMD规范更加使用运行到浏览器上,
  • 不过代码阅读和书写都比较困难

UMD

兼容 AMD 和 CommonJS 的一个模块化方案,可以同时运行在浏览器和 Node.js 环境。不做多的介绍,已经不流行了

ES6 Module

ES6 Module 也被称作 ES Module(或 ESM), 是由 ECMAScript 官方提出的模块化规范,作为一个官方提出的规范,ES Module 已经得到了现代浏览器的内置支持。

ES Module 的兼容性问题,其实 ES Module 的浏览器兼容性如今已经相当好了,覆盖了 90% 以上的浏览器份额,

不仅如此,一直以 CommonJS 作为模块标准的 Node.js 也紧跟 ES Module 的发展步伐,从 12.20 版本开始正式支持原生 ES Module。也就是说,如今 ES Module 能够同时在浏览器与 Node.js 环境中执行,拥有天然的跨平台能力。