自研模块加载器(一) 模块系统概述与自定义模块规范书写规定

模块系统概述

CommonJs/AMD/CMD/ES6 Modules

什么是模块化?

模块化就是把系统分离成独立的功能的方法,需要什么功能,就加载什么功能

当一个系统越来越复杂时候,我们会遇到这些问题

1. 命名冲突

2. 文件依赖

使用模块化开发可以避免以上问题,并提升开发效率

1. 可维护性

2. 可复用性

在生产角度,模块化是一种生产方式,这种生产方式效率高,维护成本低。

模块化开发演变

1. 全局函数

早期开发中,将重复的代码封装成函数,将多个函数放在一个文件中。 缺点: 污染全局变量,看不出相互的直接关系

2. 通过对象命名的方式

通过对象命名的形式,从某种程度上减少了变量命名冲突,但是不能从根本上解决。 缺点:内部变量可被外部改写,命名空间越来越长

3. 私有共有成员分离

利用此方式将函数包装成了独立的作用域,私有空间变量函数不会影响全局。 缺点:解决的变量冲突的问题,但是没有解决降低开发复杂度的问题。

CommonJS

CommonJS加载是同步的,也就是说加载完成才能执行后面的操作。

Node.js主要用于服务器编程,模块都是存储在本地硬盘中,加载速度快,所以Node.js 采用CommonJS规范。

CommonJS规范为三部分: Module(模块标识)、Require(模块引入)、Exports(模块定义)

Module变量在每个模块内部,就代表当前模块

Exports属性是对外接口,用于导出模块的变量和方法

Require()用来加载外部依赖,读取并执行JS, 返回该模块的Exports对象

AMD (RequireJS)

AMD也就是异步模块定义。它采用异步的方式加载模块,通过Define的方式定义模块,require方法加载模块。

定义模块:

define([tools], function(){})

如果该模块还依赖其他模块,则第一个参数以数组的形式传入依赖模块,第二个参数为自定义模块

AMD模块加载

require([‘modules‘],callback);

第一个参数 ‘modules‘ 为要加载的成员,因为是AMD异步的,所以第二个参数为模块加载完成后的回调

CMD (sea.js)

CMD即通用模块定义。CMD是国内发展出来的规范,Sea.js实现来这个规范。

在CMD规范中,一个模块就是一个文件,代码书写如下:

define(function(require, exports, module ) {
})

CMD推崇依赖就近,延迟执行,文件是提前加载好,只有在require的时候才去执行。

define(function(require, exports, module ) {
    var math = require(‘./math‘);
    math.add();
})

ES6模块化

语法简介,支持异步加载,未来可以成为浏览器和服务器通过的模块化解决方案。

ES6模块的定义:

新增 ‘import‘ 和 ‘export‘ 两个关键字

export用于暴露模块功能, import 用于引入模块提供的功能

import { foo, obj } from ‘./lib‘; // 引入模块功能
foo();//  使用方法

const foo1 = function() {}
//  导出默认 export default foo1;
export { foo1 }

ES6模块运行机制:

ES6 模块是动态引用,如果使用import 从一个模块加载变量(import foo from ‘lib‘),变量不会被缓存,而是成为一个指向被加载模块的一个引用。 等到脚本执行时,根据只读引用,到那个被加载的模块中取值。

自定义模块规范(书写约定)

自定义加载器

模块的定义:

1. 约定:所有的Javascript文件都应该用模块的形式来书写,并且一个文件只能包含一个模块;

2. 使用全局函数define来定义模块 define(factory[require,exports,module]));

3. factory函数在调用时,会始终传递三个参数: require,exports和module, 这三个参数在所有的模块代码里可以用

define(function(require, exports, module)) {
  // 模块代码
})

模块加载器会从factory.tostring()中解析出来当前模块依赖的模块, 它是一个由模块标识组成的数组。

exports用来向外提供模块的api || 使用return直接向外提供api

require 函数用来访问其他模块提供的api

module 参数存储模块的元信息(id是模块的唯一标识, deps依赖泪奔 exports对外提供的接口对象)

注意:

1. 在模块代码中, 第一个参数必须命名为 require

2. 不要重命名require函数,或在任何作用域中给require重新赋值

3. require的参数值必须是字符串直接量,不能是表达式。

原文地址:https://www.cnblogs.com/zzd0916/p/12232913.html

时间: 2024-10-11 05:29:43

自研模块加载器(一) 模块系统概述与自定义模块规范书写规定的相关文章

自研模块加载器(四) 模块资源定位-异步加载

资源定位-动态加载 通过resolve方法进行异步解析,完整解析如下图所示: 根据上篇文章startUp.js代码,我们继续完善本章动态加载资源的代码. (function(global) { var startUp = global.startUp = { version: '1.0.1' } var data = {}; // 获取当前模块加载器配置信息 var cache = {}; // 缓存 //模块的生命周期 var status = { FETCHED: 1, SAVED: 2,

JavaScript AMD 模块加载器原理与实现

关于前端模块化,玉伯在其博文 前端模块化开发的价值 中有论述,有兴趣的同学可以去阅读一下. 1. 模块加载器 模块加载器目前比较流行的有 Requirejs 和 Seajs.前者遵循 AMD规范,后者遵循 CMD规范.前者的规范产出比较适合于浏览器异步环境的习惯,后者的规范产出对于写过 nodejs 的同学来说是比较爽的.关于两者的比较,有兴趣的同学请参看玉伯在知乎的回答 AMD和CMD的区别有哪些.本文希望能按照 AMD 规范来简单实现自己的一个模块加载器,以此来搞清楚模块加载器的工作原理.

自研模块加载器(三) module模块构造器设计-模块数据初始化

依赖加载策略 模块数据初始化 status状态生命周期 代码展示 demo包括4个文件, index.html , a.js , b.js , startUp.js index.html <!DOCTYPE html> <html> <head> <title>自研模块加载器</title> </head> <body> <script src="./startUp.js"></scr

自研模块加载器(二) 加载器结构与设计导论

结构导论 模块部分 数据初始化: 加载器中设计来一个名为Module的构造函数,每个模块都是此构造函数实例对象.构造函数中给实例对象扩展了"未来"所需用到的属性和方法. 模块存储: 加载器中设计来一个名为cache的缓存对象,每个文件(模块)都会存储在cache对象中. 具体存储方式: { "当前模块的绝对路径" : new Module()}, 注意: 当前模块的绝对路径是通过资源部分,资源定位方法实现的. 每个模块创建都先初始化数据,存储在缓存对象中. 资源部分

【模块化编程】理解requireJS-实现一个简单的模块加载器

在前文中我们不止一次强调过模块化编程的重要性,以及其可以解决的问题: ① 解决单文件变量命名冲突问题 ② 解决前端多人协作问题 ③ 解决文件依赖问题 ④ 按需加载(这个说法其实很假了) ⑤ ...... 为了深入了解加载器,中间阅读过一点requireJS的源码,但对于很多同学来说,对加载器的实现依旧不太清楚 事实上不通过代码实现,单单凭阅读想理解一个库或者框架只能达到一知半解的地步,所以今天便来实现一个简单的加载器 加载器原理分析 分与合 事实上,一个程序运行需要完整的模块,以下代码为例: 1

JS模块加载器加载原理是怎么样的?

路人一: 原理一:id即路径 原则.通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) .这里的 'a'.'b' 都是 ModuleId.通过 id 和路径的对应原则,加载器才能知道需要加载的 js 的路径.在这个例子里,就是 baseUrl + 'a.js' 和 baseUrl + 'b.js'. 但 id 和 path 的对应关系并不是永远那么简单,比如在 AMD 规范里就可以通过配置 Paths 来给特定的 id 指配 path. 原理二:crea

js模块化/js模块加载器/js模块打包器

之前对这几个概念一直记得很模糊,也无法用自己的语言表达出来,今天看了大神的文章,尝试根据自己的理解总结一下,算是一篇读后感. 大神的文章:http://www.css88.com/archives/7628(大神的文章写的很详细,建议先看完大神的文章) 一.js模块化 什么是js模块化,我们从历史说起. 1.一开始我们怎么写脚本?就是在html文件中用<script></script>写代码 这种方式的缺点:代码复用靠复制,基本是全局变量. 2.后来我们用js文件写代码,用<

Sea.js 是一个模块加载器

1 模块定义define define(function(require,exports,module){ //require 引入需要的模块如jquery等 //var $ = require('./jquery'); //exports可以把方法或属性暴露给外部 exports.name = 'hi'; exports.hi = function(){ alert('hello'); } //module提供了模块信息 }); 2 使用定义好的模块seajs.use <!doctype ht

模块加载器

模块加载器 最近在做新项目的时候自己利用一点业余时间写了一个简单的js模块加载器.后来因为用了webpack就没有考虑把它放到项目里面去,也没有继续更新它了.模块加载器开源的有很多,一般来说seaJS和reqiureJS都能满足基本需求.本篇博文主要分享一下卤煮写这个加载器的一些想法和思路,作为学习的记录. js模块化加载已经不是一个新鲜概念了,很多人都一再强调,大型项目要使用模块化开发,因为一旦随着项目的增大,管理和组织代码的难度会越来越难,使得我们对代码的管理变得重要起来.当然,在后端模块化