模块
模块成为了代码管理/编译,业务分离的基本单元。
本质上模块就是一个提供对外通信的接口,进行代码切分/组合的管理方式。其呈现方式因不同的模块化方案而不同,基本是以文件粒度区分。
为什么要有前端模块化
- 把复杂问题分解成多个子问题
- 关注分离
- 大型软件开发的结束基础
- 更优雅的代码管理
- 替换、复用、拓展
- 内聚(变量,行为内聚在模块内,对外暴露接口进行通信)
- 开发方式的革新
- 方便多人协同,面向过程开发
通俗来说:前端代码日益增多,避免命名冲突,更高复用性,更好的分离,按需加载…
模块化历史
- 全局 function 模式(命名冲突)
- namespace 简单对象封装(外部可以直接修改内部数据)
- IIFE 问题(依赖)
- IIFE 增强(引入依赖),现代模块化基石
现代模块化要解决的问题
- 命名污染,全局污染,变量冲突等基础问题
- 内聚且私有,变量不能被外界污染到
- 如何引入(依赖)其他模块,如何暴露出接口给其他模块
- 依赖顺序问题
目前使用最多的几种模块化方法
CommonJS
特点:同步加载,适用于服务器(多用于node),加载一次即可缓存结果。浏览器端需要编译后执行
语法:
// 暴露模块
module.exports = value;
exports.value = value;
// 导入
let example = require('./example.js')
var name = 'fj';
var age = 22;
exports.name = name;
exports.getAge = function() {
return age;
}
var a = require('a.js');
console.log(a.name); // fj
a.name = 'gx';
var b = require('a.js');
console.log(b.name); // gx
复制代码
AMD
特点:异步加载,允许指定回调函数,适用于浏览器端。
语法:
// 借助工具:RequireJS
define('a',function() {
console.log('a load');
return {
run: function() {
console.log('a run');
}
}
})
define('b',function() {
console.log('b load');
return {
run: function() {
console.log('b run');
}
}
})
require(['a','b'],function(a,b) {
console.log('main run');
a.run();
b.run();
})
// a load; b load; main run; a run; b run;
复制代码
CMD
特点:用于浏览器端,模块加载是异步的,模块使用时才会加载执行。结合了 CommonJS 和 AMD 规范的特点
语法:
// 辅助工具 sea.js
define('a',function(require,exports,module) {
console.log('a load');
exports.run = function() {
console.log(console.log('a run'))
}
})
define('b',function(require,exports,module) {
console.log('b load');
exports.run = function() {
console.log(console.log('b run'))
}
})
define('main',function(require,exports,module) {
console.log('main run');
var a = require('a');
a.run();
var b = require('b');
b.run();
})
seajs.use('main');
// main run; a load; a run; b load; b run;
复制代码
ES6 模块化
特点:编译时确定依赖关系
语法:
// 导出
let name = 'fj';
let nameFn = function() {
return `name is ${name}`;
}
export default {
name,nameFn
}
// 导入
import myObj from './export.js';
console.log(myObj.name);
console.log(myObj.nameFn());
复制代码
总结
- CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
- AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
- CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重。
- ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
其他
依赖前置,依赖后置(本质上是按需加载)
- 依赖前置是AMD:所需模块全都加载[a,b,c],
- 依赖后置是CMD:所需模块按需加载(require)
参考链接:
前端模块化详解
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END