CommonJS/AMD/UMD/ES Module介绍和区别
最近在使用Vue开发组件库时,使用lib模式打包之后的文件有xxx.common.js和xxx.umd.js,在这里做一下整理。
1、CommonJS/AMD/UMD/ES Module简介
JavaScript在发展之初,是没有模块化(module)的概念,无法将一个大的程序拆分成相互依赖的小文件,而其他语言比如Java、Python有import,而连CSS都有@import,唯独JavaScript没有。下面我们来看看JavaScript从没有到有模块化概念,在发展过程中经历了哪些阶段。
script标签:当时普遍使用一个立即执行的函数,将js代码单独包裹在一个文件里面,然后通过script标签将其进行引入,这样就能使得各自文件的js代码在各自的局部作用域执行,避免相互影响。
CommonJS: 后来随着Node.js的出现,就出现了js文件相互依赖的关系,为了解决这个给这个问题,总不能写script标签吧,于是乎就有了Common.js模块依赖的语法,引入使用,let fs = require('fs'),导出使用module.export a =1;。
AMD(异步模块定义):由于common.js是同步执行性的,用于服务端,而AMD用于浏览器,他的语法类似CommonJS,具体用法是通过回调,require(‘Vue’,(Vue)=>{new Vue})
ESMoudule:上述引入方式并存了一段时间后,制定JavaScript规范的委员会出面,也就是现在的ES6规范,通过import导入JS模块,通过export导出模块,也是用的比较多的一种,现在主流浏览器也基本支持了,在script标签中使用type='module'属性即可。
UMD(统一模块定义):这种模块语法,兼容了以上的CommonJS、AMD、ES Module使用方式,也就是Vue脚手lib模式打包的这种模式。
2、CommonJS、AMD、ES Module区别:
在es6之前,社区指定的模块加载方案主要还是CommonJS和AMD两种,前者用于服务器端,后者用于浏览器。而es6使得模块化实现更加简单,可以完全取代CommonJS和AMD规范,成为浏览器和服务端通用的而解决方案
ES6模块设计思想是尽量静态化,使得编译 时就确定模块的依赖关系,以及输入输出的变量,Common.js和AMD都是只在运行时,才确定这些关系。
比如Common.js就是对象,输入时必须查找对象属性
//CommonJS 模块 let {stat, exists, readFile} = require('fs'); //相当于 let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readFile = _fs.readFile;复制代码
上述代码的实质是整体加载 fs 模块(即加载 fs 的所有方法),生成一个对象(_fs),然后再从这个对象上读取 3 个方法。这种加载称为 "运行时加载",因为只有运行时才能得到这个对象,导致完全没有办法在编译时进行 "静态优化"。 而 ES6 模块不是对象,它是通过 export 命令显式指定输出的代码,再同构 import 命令输入。
//ES6 模块 import {stat, exists, readFile} from 'fs';复制代码
上述代码的实质是从 fs 模块加载 3 个方法,而不加载其他方法。这种加载称为 "编译时加载" 或者静态加载,即 ES6 可以在编译时就完成模块加载,效率比 CommonJS 的加载方式高。当然,这也导致 ES6 模块本身无法被引用,因为它不是对象。
作者:ALEX_@
链接:https://juejin.cn/post/7009971893281226759