前端模块化历程

背景

一个足够复杂的工程,需要尽量将功能解耦。

什么叫解耦?简单来说,需要将不同的功能分开到不同的文件中,或不同的目录结构中,形成一个个模块,模块之间通过有限的接口交互,模块内部的数据变化对外部隐藏。

在node上,这一点表现的非常不错。node实现了CommonJS规范,每个JS文件就是一个模块,模块中的所有数据对外隐藏,仅通过Module.exports暴露模块内的内容。于是,模块化开发在node环境中已不成问题。
然而,JS语言可以运行的不仅仅是node环境,它还有一个非常非常重要,也很常见的运行环境——客户端浏览器。
在浏览器一侧,我们并没有像node环境那样的模块化开发能力,于是,不可避免会遇到下列问题:

  1. 如何将代码分离
  2. 代码分离后,浏览器引用js的时候,如何处理它们之间的依赖关系?
  3. 代码分离后,浏览器引用js会导致额外的请求发生,如何解决效率问题?

第三方模块化规范

AMD规范

AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

    require([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

	require(['math'], function (math) {
	    math.add(2, 3);
	});
CMD规范

前端大牛玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的,不过用起来感觉更加方便些,最重要的是中文版(http://seajs.org/docs/#docs)

seajs看起来像这样:

	define(function(require,exports,module){    //...});
ES6的模块化

然而,这一切都在慢慢的成为历史,当ECMAScript6出世之后,模块化的规范,终于有了官方的标准。

它的大致规则如下:

  1. 一个JS文件,即一个模块
  2. 模块中所有的数据,除非导出,否则都是私有数据,仅能在模块中访问
  3. 使用export关键字导出模块
  4. 使用import关键字导入模块,导入时使用解构表达式得到导出的数据,否则,将使用导出的默认数据
  5. 一个模块可以有多个导出
  6. 导入的模块会被缓存
  7. 在页面中加载入口模块使用 <script type="module" src="入口模块">
模块导出

你可以使用 export 关键字将已发布代码部分公开给其他模块。最简单方法就是将 export放置在任意变量、函数或类声明之前,从模块中将它们公开出去,就像这样:

	//mymodule.js// 导出数据
	export  var color = "red";
	export  let name = "Nicholas";
	export  const magicNumber = 7;// 导出函数
	export  function sum(num1, num2) {    return num1 + num2;
	}
	// 导出类
	export class Rectangle {
	    constructor(length, width) {
	            this.length = length; 
	            this.width = width;
	 		}
	}
	// 此函数为模块私有
	function subtract(num1, num2) {
	   return num1 - num2;
	}
	// 定义一个函数……
	function multiply(num1, num2) {  
	  return num1 * num2;
	}
	// ……稍后将其导出
	export {
	    multiply
	};
模块导入

一旦你有了包含导出的模块,就能在其他模块内使用 import 关键字来访问已被导出的功能。

	import { color, name, Rectangle, multiply } from "./mymodule.js";
导入导出默认值

在ES6中,为了简化导入导出语法,还提供了一种导入导出的方式——默认值,使用这种方式导入导出会更加简单,但要注意的是,每个模块只能导出一个默认值

1.导出默认值:

	export default function(num1, num2) {    
		return num1 + num2;
	}

2.导入默认值:

	import sum from "./example.js";
ES6模块语法
代码含义
export const name = 'Jake';导出变量
export function sayHello() { }导出函数
export class SayHello { };导出类
export default class SayHello { };导出默认类
export default function SayHello() { };导出默认函数
const name = 'Jake';function sayHello() { }; export { name, sayHello };导出存在的变量
export { name as person, sayHello };使用别名导出变量
import SayHello from "SayHello.js";导入默认导出
import {name,SayHello} from "SayHello.js";导入命名导出
import * as SayHello from "SayHello.js";导入模块中声明的全部导出内容
import {name as person} from "SayHello.js";通过别名导入模块中声明的全部导出内容
在浏览器中使用入口模块

在nodejs中,我们可以使用node app.js来运行某个用于启动的模块,在浏览器中如何操作呢?
浏览器是以页面为启动单元来运行js程序的,也就是说,js必须要被页面引用后方可运行。对于模块化的js代码,需要在页面中使用下面的方式启动

	<script type="module" src="./app.js"></script>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值