最近在看vue源码,而后看到了rollup,而后又看到了模块化的概念,因此对模块化的概念进行一个学习和总结。如下就是个人学习成果,若是有什么不对的欢迎指教。javascript
模块化存在的意义:开发者但愿在开发过程当中只须要关注本身的核心业务逻辑,其余的能够直接加载别人写好的模块。可是Javascript不是一种模块化编程语言,在es6之前,它是不支持”类”(class),因此也就没有”模块”(module)了(借鉴而来)vue
nodejs一个应用于服务器端编程被提出时,Javascript模块化也所以诞生,CommonJS模块规范被提出。在es6模块以前,CommonJS统一了模块化编程。java
下面我要简述一下CommonJS、AMDCMD和ES6 Modulenode
在CommonJS中有一个全局的方法require(),能够用于加载模块。可是这个方法在浏览器端具备必定的局限性,由于JavaScript是解释性语言,从上而下直接执行。此时的困惑是es6
后来我获得的答案:编程
最后个人笔记:
CommonJS是一种同步加载的方式,在服务器端模块是存在本地的,这样读取时间很快,须要等待时间很短,能够是同步加载,可是在浏览器端,依赖的模块是存放在服务器端的,读取的时间依赖网速,若是网速很差的话,须要等待好久。javascript就会报错了,因此在浏览器端须要异步加载的方式浏览器
let num = 0 function add (a, b) { return a + b } module.exports = { num: num, add: add }
exports 和 module.exports的区别:Node为每个模块都提供了一个exports变量,指向module.exports。 服务器
以上的写法module.export尝试写成:异步
// 结果报错 let num = 0 function add (a, b) { return a + b } exports = { num: num, add: add }
第二种写法:编程语言
// 结果成功 let num = 0 function add (a, b) { return a + b } exports.num = num exports.add = add
node中,exports指向module.exports。若是直接将一个对象赋值给exports,那么exports原先指向module.exports会被破坏,这样这两种之间就没有联系了,就会报错。若是非要想用exports的话,能够直接给exports添加属性。
let math = require('./math')
// 所有加载 import * as util from 'xxx' import AA from 'yyy' // 按需加载 import { A, B } from 'xxx'
import * as aa from 'xxx'的语法,会将xxx文件内export的函数整合成一个对象。
import AA from 'yyy',引入的是export default的函数
import 在编辑时就执行的,因此:
foo() import { foo } from 'xxx'
不会报错,由于import { foo } from 'xxx'在编辑时就执行了,foo()是在运行时才执行。
import命令是在编辑时就会执行的,因此没法作到放到if代码中或者函数中,
if (a) { import { foo } from 'xxx' } // 会报句法错误
import export只能在模块的顶层,不能够在代码块中,这样就没法实现运行时动态加载模块(条件加载)。 => import()的出现
使用import()能够相似node里的require(),能够动态加载且import()是异步加载。import()加载模块成功之后,这个模块会做为一个对象当then方法的参数。
import('xxx').then(module => { ... })
export 规定的时对外的接口,必须模块内部的变量创建一一对应关系。看到阮一峰大佬的内容里有这么一段:
目前仍是不很理解:为何export var m = 1 或者export function aa (){}就能够创建一一对应的关系。
以前一直没有考虑过他们以前的区别,今天又仔细研读了一下阮一峰的es6关于模块的讲解,以为说的很好。
ES6的设计思想是尽可能的静态化,在编译时就能够肯定模块之间的依赖关系,以及输出和输入的变量
CommonJS、AMD、CMD只能在运行时才能够肯定模块之间的加载关系。
// CommonJS let { stat, exists, readFile } = require('fs'); // ES6 import { stat, exists, readFile } from 'fs';
第一个和第二的区别:
CommonJS是将fs模块总体加载出来生成一个对象,而后在这个对象读取里找stat, exists, readFile方法,这种就是运行时加载
ES6模块会只在fs中加载stat, exists, readFile这三个方法,不会加载其余方法,这种就是编辑时加载