一.什么是前端模块化
模块化就是把一个较为复杂的程序按照一定的规范拆分并且封装成几个单独的代码文件,在使用的时候按照一定的规则将这些文件组合在一起。每个代码文件中的数据是私有的,通过向外部暴露一些接口或者是一个方法来实现和其他模块间的通信。
二.模块化可以解决什么问题
- 命名冲突:解决不同脚本文件中的变量引起的命名冲突的现象
- 可以提高代码的复用性
- 依赖管理复杂的问题,解决了需要手动维护脚本之间的依赖关系
二.CommonJS
CommonJS最初是在浏览器以外的地方使用,主要是在服务器端使用,CommonJS模块化有以下几个特点
- 同步加载:模块在代码运行的时候同步加载,适用于服务端,但是一般不能在浏览器环境,因为在浏览器环境中同步加载会阻塞渲染的进程
- 缓存机制:同一个模块在多次加载的时候会被缓存,除非明确清除缓存
- 通过关键字require和module.exports实现模块的导入和导出
- require函数可以实现导入其他模块,比如自定义模块,系统模块以及第三方库模块等
示例:
//name.js
const name="this is index.js"
const outputName=()=>{console.log(name);
}
module.exports={outputName,
}//index.js
const {outputName}=require('./name.js');
const main=()=>{console.log(this is index.js);outputName();
}
exports=main;
实现原理:首先require函数会接收一个参数——文件标识符,通过文件标识符在module上查找有没有缓存,如果有缓存直接返回缓存里的内容;如果没有缓存,会创建一个module对象,缓存到module上,然后执行相应的文件,加载完相应的文件。
三.ESmodule
ES6 module的模块引入和导出是静态的,使用export和import关键字来进行模块的导出和导入,有命名导出和默认导出两种导出方式。
命名导出:可以导出多个变量,函数或者是类,并且在导入使用的时候需要按名字导入
默认导出:每个模块只能有一个默认导出,导入使用的时候可以自定义导入的名称。
特点:
- ES模块式是单例的,也就是每个模块只会被加载和执行一次,后续的导入都引用的是相同的模块实例。可以保证模块的状态在多个导入中是共享的
- ES模块默认处于严格模式,也就是说无法使用一些不严格符合语法的JS代码,这样可以提高代码的安全性和可读性
- ES模块也支持动态导入,通过import()函数可以在代码执行的时候按需加载模块,并且ES模块是异步加载的,不会阻塞浏览器进程的渲染
示例
//module.js
let count = 0;
export const increment = () => count++;
export const getCount = () => count;
//main.js
import { increment, getCount } from './module.js';
increment();
console.log(getCount()); // 1
increment();
console.log(getCount()); // 2