一、CommonJS:服务端模块化规范

1、加载机制:输入的是被输出值的拷贝。一旦输出,模块内部变化就影响不到这个值。

2、所有代码都运行在模块作用域。

3、模块可以多次加载,但只在第一次加载时运行一次,其结果会被缓存。后面再加载的时候,就直接读取缓存结果。要想让模块再运行的话,,必须清除缓存。(delete require.cache[moduleName])

4、模块加载的顺序,按照其在代码中出现的顺序。

5、module对象:

  • module.id:模块的标识符,通常是带有绝对路径的模块文件名。
  • module.filename: 模块的文件名,带有绝对路径。
  • module.loaded:模块是否已经加载完成。
  • module.parents:[],调用该模块的模块。node下执行,会得到null或者undefined,require引入的会返回它的调用模块。可以用此判断该模块是不是入口模块。
  • module.exports:表示模块对外输出的值。还有个exports变量,指向的是module.exports。不能直接将 exports 变量指向一个值,因为这样等于切断了 exports 与 module.exports 的联系。

    6、require:用于加载模块文件。

  1. 步骤:读入并执行一个js文件,返回该模块的exports对象。若没有发现指定模块则报错。
  2. 加载规则:加载文件的后缀默认是.js。 | require参数 | 加载规则 | | —- | —- | | ‘/‘开头 | 加载的是绝对路径的文件 | | ‘./‘开头 | 加载的是相对路径的文件 | | 不以/或者./开头 | 默认提供的核心模块(位于Node的系统安装目录中)或者一个位于各级node_modules目录的已安装模块 | | 不以/或./开头,是一个路径 | 先找第一级的位置,再依次往后续找 |

指定的模块没发现的话,node会尝试为文件名添加.js,.json,.node后缀来找。

  1. require.resolve可以拿到require命令加载的确切文件名。

    7、输出的是值的缓存。

    二、AMD(Async Module Definition)提供一个浏览器端的模块解决方案

三、UMD(Universal Module Definition)希望提供一个前后端跨平台的解决方案

  • 以此判断是否支持Nodejs模块格式:(typeof exports === ‘object’),是否支持AMD(typeof define === ‘function’),都不支持则将模块公开到全局(window或global)。

四、ES6 Module:浏览器和服务器通用的模块解决方案

1、静态化。编译时就能确定模块的依赖关系;commonjs和AMD只能在运行时确定。

  • 不在需要UMD模块格式了。
  • 不再需要对象作为命名空间。
  • 将来浏览器新的API就能用模块格式提供,不在必须做成全局变量或者navigator对象的属性。

    2、es6模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。缺点:没法引用es6模块本身,因为它不是对象。

    3、自动采用严格模式,所以严格模式的规则,es6模块要遵守。

    4、导入和导出:import和export。

  1. 都可以使用as别名。export语句输出的接口,与其对应的值是动态绑定的。
  2. 可以出现在模块顶层的任何位置,不能处于块级作用域内,否则会报错。因为这样就没法做静态优化了。
  3. import命令输入的变量都是只读的。不允许在加载模块的脚本里面改写接口。以下情况要注意: ```javascript import { a } from ‘./xxx.js’ a = {}; // 报错,a是只读的

a.foo = ‘hello’; // 不报错,但是其他模块也可以读到改写后的值,引起bug,所以不能这么操作。

  1. 1. import命令有提升效果,会提升到整个的头部。本质:import是静态的,在编译阶段执行,所以import也不能使用表达式或者变量表示。
  2. 1. import会执行所加载的模块,不可省略模块后缀名。
  3. ```javascript
  4. import './test.js'; // 会直接加载并执行test.js的代码。
  1. 尽量不要把require和import在一个文件里混用。在一起用的话会先执行import的。

    5、es6module可以继承

    ```javascript // circleplus.js

export * from ‘circle’; export var e = 2.71828182846; export default function(x) { return Math.exp(x); } ```

五、Webpack的模块机制实现