如果有一天自己用typescript 写一个库,或者插件,或者在使用一个框架和库的时候,如果去看它的声明文件或者自己去定义声明文件。第一步,先认识前端现有的几种模块化方式。
1.认识js模块化的几种方式
使用方法及其源码来识别库的类型。 根据库的文档及组织结构不同,来判断
全局库 :许多库都是简单的暴露出一个或多个全局变量。目前,大多数流行的全局访问型库实际上都以umd库的形式进行书写(见后文)。 umd库的文档很难与全局库文档两者之间难以区分。 在书写全局声明文件前,一定要确认一下库是否真的不是umd。
由于把一个全局库转变成umd库是非常容易的,所以很少流行的库还再使用全局的风格。 然而,小型的且需要dom(或 没有依赖)的库可能还是全局类型的。
模块化库
许多流行的node.js库都是这种模块化的,例如express,gulp和 request。
umd
umd模块是指那些既可以作为模块使用(通过导入)又可以作为全局(在没有模块加载器的环境里)使用的模块。 许多流行的库,比如 moment.js,就是这样的形式。 比如,在node.js或requirejs里,你可以这样写:
然而在纯净的浏览器环境里你也可以这样写:
umd模块会检查是否存在模块加载器环境。 这是非常形容观察到的模块,它们会像下面这样:
如果你在库的源码里看到了typeof define,typeof window,或typeof module这样的测试,尤其是在文件的顶端,那么它几乎就是一个umd库。
大多数流行的库现在都能够被当成umd包。 比如 jquery,moment.js,lodash和许多其它的。
es6 模块化
历史上,javascript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 ruby 的require、python 的import,甚至就连 css 都有@import,但是 javascript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。
commonjs用于服务器,amd用于浏览器。es6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 commonjs 和 amd 规范,成为浏览器和服务器通用的模块解决方案。
es6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。commonjs 和 amd 模块,都只能在运行时确定这些东西。比如,
上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
es6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
二、amd,cmd,commonjs 三种模块化的代码风格
require.js (amd) 模块化加载
amd,即 (asynchronous module definition),这种规范是异步的加载模块,requirejs应用了这一规范。先定义所有依赖,然后在加载完成后的回调函数中执行:
具体可参考https://www.runoob.com/w3cnote/requirejs-tutorial-2.html
代码书写方式

commonjs
node 应用由模块组成,采用 commonjs 模块规范。 具体可参考
http://javascript.ruanyifeng.com/nodejs/module.html
cmd(sea.js)
具体可以参考
https://www.zhangxinxu.com/sp/seajs/docs/zh-cn/module-definition.html
es6 的import 和export
其它的书写方式可以参考
https://es6.ruanyifeng.com/#docs/module#export-%e5%91%bd%e4%bb%a4
参考
四、认识umd
(1)是什么(解决什么问题,及应用场景)
umd 叫做通用模块定义规范(universal module definition)它可以通过运行时或者编译时让同一个代码模块在使用 commonjs、cmd 甚至是 amd 的项目中运行。未来同一个 javascript 包运行在浏览器端、服务区端甚至是 app 端都只需要遵守同一个写法就行了
(2) 代码结构
(3)手写一个例子
1.新建一个umd-module.js
2,挂载在window上的情况