javascript之模块加载方案
前言
主要学习一下四种模块加载规范:
- AMD
- CMD
- CommonJS
- ES6 模块
历史
require.js
requirejs 为全局添加了 define 函数,你只要按照这种约定的方式书写这个模块即可。
define(function () {
//Do setup work here
return {
color: "black",
size: "unisize"
}
});
//my/shirt.js now has some dependencies, a cart and inventory
//module in the same directory as shirt.js
define(["./cart", "./inventory"], function(cart, inventory) {
//return an object to define the "my/shirt" module.
return {
color: "blue",
size: "large",
addToCart: function() {
inventory.decrement(this);
cart.add(this);
}
}
}
);
以上示例代码来源于require.js官网
demo代码详见 https://github.com/BillyQin/jsModule/tree/master/requireJs
AMD
require.js 为全局添加了define 函数,按照这种约定方式写即可。
这个约定方式就是AMD(The Asyncchronous Module Definition)
所以AMD规范就是定义了怎么写define函数。只要按照这个规范来写模块和依赖,require.js就能正确解析。
sea.js
demo代码详见 https://github.com/BillyQin/jsModule/tree/master/seaJs
CMD
同样的道理,CMD就是Sea.js对模块定义对规范化产出。
所以CMD的内容就是描述该如何定义模块,如何引入模块,如何导出模块。只要按照这个规范来写模块和依赖,sea.js就能正确解析。
AMD 和 CMD
- AMD 推崇依赖前置,
CMD推崇依赖就近
- 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
- AMD 是将需要使用的模块先加载完再执行代码
- CMD 是在 require 的时候才去加载模块文件,加载完再接着执行。
CommonJS
AMD 和 CMD 都是用于浏览器的模块规范,而在服务端(node),则采用CommonJS。
CommonJS和sea.js一样,require的时候才去加载模块文件,加载完再接着执行。
demo代码详见 https://github.com/BillyQin/jsModule/tree/master/commonJs
为什么浏览器中不支持 CommonJS 语法呢?
这是因为浏览器环境中并没有 module、 exports、 require 等环境变量。
ES6
es6定义了新的模块加载方案。
// 导出
const addr = 'China'
const year = 2018
export { addr, year }
// 导入
import { addr, year } from './index.js'
和require.js(AMD)一致,将需要使用的模块加载完再执行代码。
ES6 和 CommonJS的差异
CommonJS模块输出值的拷贝, ES6输出值的引用。 CommonJS模块输出值的拷贝, 也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
CommonJS是运行时加载,ES6是编译时输出接口。 CommonJS加载的是一个对象,就是module.exports属性。该对象只有在脚本运行完成后才会生成。而es6模块不是对象,对外接口只是一种静态定义,在代码静态解析阶段就会生成。
Babel
在浏览器不支持es6的时候,如果要使用es6的语法,一般都会在项目里加入babel。
// es6
let firstName = 'Michael';
const lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
转换后
Object.defineProperty(exports, "__esModule", {
value: true
});
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
exports.firstName = firstName;
exports.lastName = lastName;
exports.year = year;
webpack
Babel 只是把 ES6 模块语法转为 CommonJS 模块语法,而浏览器不支持CommonJs。这时候webpack出动。
浏览器不支持CommonJs的本质是因为浏览器环境中并没有 module、 exports、 require 等环境变量。 webpack 打包后的文件之所以在浏览器中能运行,就是靠模拟了这些变量的行为。
webpack怎么模拟呢?
// commonJs
let multiply = require('./multiply')
console.log('加载 square 模块')
let square = function (num) {
return multiply.multiply(num, num)
}
module.exports = {
square: square
}
模拟后:
// 包裹一层,注入这些变量
function(module, exports, require) {
console.log('加载了 square 模块');
var multiply = require("./multiply");
module.exports = {
square: function(num) {
return multiply.multiply(num, num);
}
};
}
整个CommonJs项目改写后
// 自执行函数
(function(modules){
// 存储已加载的模块
var installModules = {}
// 关键的require方法
function require(moduleName) {
if (installModules.moduleName) {
return installModules.moduleName.exports
}
var module = installModules[moduleName] = {
exports: {}
}
modules[moduleName](module, module.exports, require);
return module.exports;
}
return require('main')
})({
'main': function(module, exports, require) {
var addModule = require("./add");
console.log(addModule.add(1, 1))
var squareModule = require("./square");
console.log(squareModule.square(3));
},
'./add': function(module, exports, require) {
console.log('加载 add 模块')
var add = function (x, y) {
return x + y
}
module.exports = {
add: add
}
},
'./multiply': function(module, exports, require) {
console.log('加载 multiply 模块')
var multiply = function (x, y) {
return x * y
}
module.exports = {
multiply: multiply
}
},
'./square': function(module, exports, require) {
console.log('加载 square 模块')
var multiply = require('./multiply')
var square = function (num) {
return multiply.multiply(num, num)
}
module.exports = {
square: square
}
}
})
参考
javascript之模块加载方案的更多相关文章
- ECMA Script 6_模块加载方案 ES6 Module 模块语法_import_export
1. 模块加载方案 commonJS 背景: 历史上,JavaScript 一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来. 其他语言都有这项功能: ...
- javascript 异步模块加载 简易实现
在javascript是没有类似java或其他语言的模块概念的,因此也不可能通过import或using等关键字来引用模块,这样造成了复杂项目中前端代码混乱,变量互相影响等. 因此在复杂项目中引入AM ...
- JavaScript AMD 模块加载器原理与实现
关于前端模块化,玉伯在其博文 前端模块化开发的价值 中有论述,有兴趣的同学可以去阅读一下. 1. 模块加载器 模块加载器目前比较流行的有 Requirejs 和 Seajs.前者遵循 AMD规范,后者 ...
- [JavaScript] 前端模块加载简单实现(require)
模块加载的简单实现 (function(win) { var baseUrl; var paths; var script_cache = {}; var script_queue = []; var ...
- requirejs解决异步模块加载方案
他首先会遍历enableRegistry取出其中定义的模块,并且将没有加载成功的模块标识注入noLoads数组,如果过期了这里就会报错 如果上述没问题还会做循环依赖的判断,主要逻辑在breakCycl ...
- 关于javascript模块加载技术的一些思考
前不久有个网友问我在前端使用requireJs和seajs的问题,我当时问他你们公司以前有没有自己编写的javascript库,或者javascript框架,他的回答是什么都没有,他只是听说像requ ...
- ES6模块加载
两种加载方式 加载方式 规范 命令 特点 运行时加载 CommonJS/AMD require 社区方案,提供了服务器/浏览器的模块加载方案 非语言层面的标准 只能在运行时确定模块的依赖关系及输入/输 ...
- 关于前端JS模块加载器实现的一些细节
最近工作需要,实现一个特定环境的模块加载方案,实现过程中有一些技术细节不解,便参考 了一些项目的api设计约定与实现,记录下来备忘. 本文不探讨为什么实现模块化,以及模块化相关的规范,直接考虑一些技术 ...
- 小矮人Javascript模块加载器
https://github.com/miniflycn/webkit-dwarf 短小精悍的webkit浏览器Javascript模块加载器 Why 我们有许多仅基于webkit浏览器开发的应用 无 ...
随机推荐
- 基于python xlsxwriter、xlrd 生成测试报告
import xlsxwriter,xlrd ''' 思路: 1.获取数据 2.整合数据 3.写入文件 ''' #筛选 def filt(category,table,filt_name=None,r ...
- 面试bb
1.面试者进行自我介绍 2.学校/学历/大学生活及课程的心得总结(人品,性格评估) 3.技能介绍(是否对应聘工作有帮助,评估学习能力):编程/操作系统/测试工具/测试方法/脚本 4.离职原因/项目经验 ...
- 网络编程_socketserver
一.socketserver 网络编程 1.socketserver支持多用户并发处理:2.socketserver是对socket的再封装;处理步骤:1.创建一个socketserver类2.继承B ...
- python第十二周:MySql
MySql数据库 MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司.MySQL 是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不 ...
- Python基础-判断闰年
输入一个年份,判断该年份是否是闰年并输出结果.求它是否是闰年?要求:能被4整除不能被100整除或者能被400整除. y=input('请输入年份:') if(y%4==0 and y%100 != 0 ...
- 《Java JDK 8 学习笔记》序
摘录自<Java JDK 8 学习笔记> 翻开一本书,无非是想从书中得到知识,只是为何你要得到书中的知识,才是我想知道的答案,而这个答案决定了你在取得知识的过程中是否快乐! 多数人在取得知 ...
- Django——6 模型基础ORM 数据库连接配置 模型的创建与映射 数据的增删改查
Django Django的ORM简介 数据库连接配置 模型的创建与映射 数据库的增删改查 增数据 查数据及补充 改数据 删数据 Django的ORM系统分析 ORM概念:对象关系映射(Objec ...
- java debug jdk(转载)
Debug info unavailable 解决之道 从事Java的小伙伴们估计都有断点代码的习惯,可以很方便的查看运行期代码中一些变量的值. 但是JDK中有些类你会发现是无法断点的,即使你在IDE ...
- iptables防火墙原理详解+mysql pt工具
http://seanlook.com/2014/02/23/iptables-understand/
- js判断object的具体类型(或者说判断object的类class)
The JavaScript specification gives exactly one proper way to determine the class of an object: Objec ...