简介

一、为什么要模块化

模块化解决的问题:

1.全局变量污染:变量重名覆盖问题

2.变量保护:使用命名空间模拟模块化时,一个模块修改另一个模块的值,另一个模块不知情

3.梳理模块间依赖关系:模块间的执行顺序和依赖关系需要梳理

二、模块化历程

module

1.CommonJs

node.js内置使用的一种规范(逐渐废弃,而改用esmodule),规范就是规范,没有为什么

cjs规定每个js文件就是一个模块,每个模块都有require和module变量

require读取和执行js文件,是在运行时同步加载执行的,所以不适用于浏览器,会阻塞页面渲染;

module有个exports属性,包括了导出的对象,require获取的就是module.exports对象

2.AMD,CMD

这两种模块化规范是由社区人员提出的,对应amd由require.js(为了异步加载模块,适用于浏览器),对应cmd有sea.js(阿里的玉伯写的,为了能像cjs一样清新的写法并且像amd一样的异步加载),这是两个js库,是对两种规范的实现,提供了模块化的方案,提供了接口实现模块的导入和导出

3.ESModule

以上规范都是要运行时才能确定导出内容,esmodule是编译时确定依赖关系

esmodule是语言标准层面的一种规范,amd、cmd是社区提出的一种规范

核心:export,export default, import

谷歌浏览器61版本后支持此语法

浏览器加载es6模块,需要在script上加上type=”module”,就会异步加载,并且等解析html完成才会按引入顺序执行脚本,类似加了defer。使用type=”module”的同时也可以使用async,使用async后会异步加载脚本,加载完就立即执行,多个脚本的话就是按加载完成的顺序而不是引入的顺序执行

deferasync

三、esmodule和cjs的区别

1.cjs导出的是一个值的拷贝,再修改模块内外互相不影响;esmodule导出的是值的引用

2.cjs是运行时加载,因为加载的是一个对象,所以执行完脚本才生成对象;esmodule是编译时输出接口,代码静态解析阶段生成

3.cjs的require()是同步加载,esmodule的import是异步加载

4.cjs会在第一次加载后缓存模块,esmodule不会,当js引擎对脚本静态分析时,读到import命令,生成一个只读引用,当执行时再去模块中取值,动态引用,不会缓存值。