前端模块化之CommonJS,ES6,AMD,CMD
最近在搞跨平台解决方案,讨论关于模块划分的问题以及如何尽量多的复用逻辑代码。于是就有了此文章,之前的博客也写过,不过由于主机商跑路,宝贵的资源也就没了,说多了都是泪~ 这里按模块化发展的历史回溯的时间序
一. ES6 Moudle
这个是目前前端小伙伴接触的最多的,是浏览器和服务端通用的模块化解决方案,主要命令为:export
和import。export
用于导出本模块对外的接口,import
用于导入某个模块的功能。
//modulA.js
export var goingta = "goingta";
export function hello() { console.log("hello world"); }
const fn = function() { goingta = "new goingta"; console.log("fn"); };
export { fn };
const come = 1; export default come;
// export default const errorDefault = 2 // default 不能导出变量表达式
//index.js
import come, { fn, hello } from "./moduleA.js";
import * as aModule from "./moduleA.js";
fn();
hello();
console.log("come", come);
console.log("aModule", aModule); //aModule Module{default: 1, fn: ƒ (),…}
console.log("aModule.goingta", aModule.goingta); //new goingta
从上面例子,我们可以看到export
可以在任意地方导出变量,方法,并且也可以将已有变量或方法包在一个{}
对象里面导出,但是最终都会包在一个{}
里面,简单理解就是:
1. 如果单独导出一个变量或方法则是往将要导出{}对象里面添加属性。
2. 如果导出的是{},则和已生成的导出{}对象合并。
然后说一下特例export default
,这个是在导出对象里面加一个default
属性,还有一点值得注意的是export default
后面不能跟变量表达式。
最后还有一个重点是,ES6 Moudle是编译时输出,并且是值引用。
二. CommonJS
CommonJS
最主要的代表就是Node.js
,主要命令:module
、exports
、require
。其中有个令人疑惑的点是exports
和module.exports
,其实理解起来也很简单,就是在模块里面加了一句: exports = module.exports = {};
exports
和module.exports
指向同一个内存区域,只要在exports
加了属性,则module.exports
会跟着变化,但是最终导出对外的接口是以module.exports
为准,所以不推荐直接使用exports
。例如:
//moduleA.js
let goingta = "我是goingta";
exports.goingta = goingta;
exports.fn = function() { goingta = "new goingta"; };
exports = "把exports指向其他区域";
module.exports = "我现在没有goingta了,也没有fn了"; // 这行代码注释掉会有不一样的结果
// index.js
let obj = require("./moduleA.js");
console.log(obj);
最终输出的是:"我现在没有goingta了,也没有fn了",如果把最后一行代码注释掉则输出:{goingta: "我是goingta", fn:ƒ ()}
对于CommonJS
规范来说,很重要的一点是CommonJS
输出的是一个值拷贝,并且是运行时加载。
把上面的示例代码简化一下就可以看出:
//moduleA.js
let goingta = "我是goingta";
module.exports = { goingta };
module.exports.fn = function() { goingta = "new goingta"; };
//index.js
let obj = require("./moduleA.js");
obj.fn();
console.log("obj.goingta", obj.goingta);
最终结果输出:"我是goingta"
三. ES6 Module和CommonJS的区别
从上面的结论我们不难得出,ES6 Module
和CommonJS
的本质区别:
1. 引用方式:CommonJS模块输出是值的拷贝,ES6 Module模块输出的值是引用
2. 时机:CommonJS是运行时加载,ES6 Module是编译是输出
四. 模块化历史
差不多在6年前,当项目越来越大,用JS模拟划分出来的类导致文件越来越多以及需要前置依赖的各种库(那个时代的三叉戟jQuery
,Backbone
,Underscore
),模块化以及各种脚手架开始兴起,于是有了AMD
和CMD
以及当年这两种规范之争-AMD推崇依赖前置、提前执行,CMD
推崇依赖就近、延迟执行。AMD
的代表是require.js
,CMD
的代表是玉伯的Sea.js
五. AMD和CMD
AMD
规范是采用异步方式,依赖前置必须一开始就写好,所有的依赖加载完成后才会执行回调函数里的内容:
// moduleB.js
//一开始就要写好这个模块所有的依赖
define(["jQuery", "underscore", "moduleA"], function($, _) {
if (false) {
// 即便没用到moduleA,也会被提前执行
moduleA.doSomething()
}
});
`CMD`规范按玉伯大大的原话`"是 Sea.JS 在推广过程中对模块定义的规范化产出"`,并且当时在国内认可度很高。依赖就近书写:
// moduleB.js
define(function(require, exports, module) {
var moduleA = require('moduleA.js');//用到时才写
moduleA..doSomething()
//一堆其他业务代码
var $ = require('jquery.js');
$.xxxx()
});
六. 更早以前
在07年左右正式有前端开发这个职位后(以前都是后端研发兼写前端代码),SEO、性能优化、语义模板、浏览器兼容、代码混淆加密等等都需要前端开发承接是,往往是一个公用的base.js
外加几个业务js放在html
里面,然后用defer
和async
标记:
<script src="base.js" async></script>
<script src="moduleA.js" defer></script>
defer
和async
的区别在于:defer
是“渲染完再执行”,async
是“下载完就执行”。
前端模块化之CommonJS,ES6,AMD,CMD的更多相关文章
- js模块化编程之CommonJS和AMD/CMD
js模块化编程commonjs.AMD/CMD与ES6模块规范 一.CommonJS commonjs的require是运行时同步加载,es6的import是静态分析,是在编译时而不是在代码运行时.C ...
- CommonJs/ES6/AMD模块的用法以及区别
github地址: 一直以来对CommonJs/AMD/CMD/ES6的文件模块加载一直懵懵懂懂.甚至有时会将CommonJs的exports和ES6的export.default搞混.趁着学习web ...
- javascript模块化之CommonJS、AMD、CMD、UMD、ES6
javascript模块化之CommonJS.AMD.CMD.UMD.ES6 一.总结 一句话总结: CommonJS是同步加载模块,用在服务端:AMD是异步加载模块,用于浏览器端 1.为什么服务器端 ...
- 前端模块化——彻底搞懂AMD、CMD、ESM和CommonJS
我们知道,在NodeJS之前,由于没有过于复杂的开发场景,前端是不存在模块化的,后端才有模块化.NodeJS诞生之后,它使用CommonJS的模块化规范.从此,js模块化开始快速发展. 模块化的开发方 ...
- JS模块化规范CommonJS,AMD,CMD
模块化是软件系统的属性,这个系统被分解为一组高内聚,低耦合的模块.理想状态下我们只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过直接加载被人已经写好模块进行使用即可.一个模块化系统所必须的 ...
- [转]js模块化编程之彻底弄懂CommonJS和AMD/CMD!
原文: https://www.cnblogs.com/chenguangliang/p/5856701.html ------------------------------------------ ...
- (转) 前端模块化:CommonJS,AMD,CMD,ES6
模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...
- 模块化(CommonJs、AMD、CMD、UMD)发展历史与优缺点
全文主要整理自摘自<Webpack中文指南>(好文,建议直接去看,以下仅对该系列文章中的<历史发展>篇幅进行备份——也整理了点其他内容) 模块化 模块化是老生常谈了,这里不做阐 ...
- js模块化编程之彻底弄懂CommonJS和AMD/CMD!
先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写 ...
随机推荐
- [ 9.12 ]CF每日一题系列—— 960B暴力数组
Description: 给你两个数组,顺序一定,问你第一个数组连续的几个值等于下一个数组连续的几个值,然后寻找这个值得最大值,也就是满足就换 Solution: 用两个变量索引,判断即可 #incl ...
- Legal or Not HDU
Legal or Not Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- XML Publisher 并发程序由于"输出提交处理程序提交失败
http://www.cnblogs.com/benio/archive/2012/03/30/2424900.html xmlp 报表运行完成后,状态为warning,其原因大概有以下3类:1.&q ...
- 3.insert添加用法
一.新增用户接口 UserMapper.java package tk.mybatis.simple.mapper; import org.apache.ibatis.annotations.Para ...
- DELPHI微信支付代码
DELPHI微信支付代码 不管是微信支付还是支付宝支付, 3个最棘手的问题是:1,如何生成签名2,支付请求如何提交3, 如何验证签名 下面就围绕这二个问题来讲. 我使用的是XE3. 先看微信支付: ...
- 利用RGB-D数据进行人体检测 带dataset
利用RGB-D数据进行人体检测 LucianoSpinello, Kai O. Arras 摘要 人体检测是机器人和智能系统中的重要问题.之前的研究工作使用摄像机和2D或3D测距器.本文中我们提出一种 ...
- 代码面试集锦 1 - Uber
Given an array of integers, return a new array such that each element at index i of the new array is ...
- 浅谈react受控组件与非受控组件
引言 最近在使用蚂蚁金服出品的一条基于react的ant-design UI组件时遇到一个问题,编辑页面时input输入框会展示保存前的数据,但是是用defaultValue就是不起作用,输入框始终为 ...
- @JsonInclude、@JsonFormat、@DateTimeFormat注解的使用
@JsonInclude(value=Include.NON_NULL) :用在实体类的方法类的头上 作用是实体类的参数查询到的为null的不显示 @DateTimeFormat:用于接收 前端传的 ...
- 在redis中使用lua脚本
在实际工作过程中,可以使用lua脚本来解决一些需要保证原子性的问题,而且lua脚本可以缓存在redis服务器上,势必会增加性能. 不过lua也会有很多限制,在使用的时候要注意. 在Redis中执行Lu ...