专栏首页carven前端模块化开发

前端模块化开发

其实对前端模块化开发的接触时间并不多,很多见解都是别人的,或者是偏的, 还是乐意记录下来,谁让我一天一个念头 说到前端模块化开发,其实是说 javascript 模块化开发。 目前,大众讲到的 javascript模块化规范 有3种,CommonJSAMD(异步模块定义)、CMD(通用模块定义)

CommonJS

CommonJS在 node 端模块采用的规范。 根据CommonJS规范,每一个文件都是一个模块,每一个模块都有一个独立的作用域,文件内的变量都是私有的,其他文件不可使用(除非 赋值到 global上) 每个文件对外的接口是 module.exports 对象。其他文件通过使用这个对象的属性和方法,实现对本文件的使用。

require用于引用其他模块,实际获得的是其他模块的module.exports对象。

例子

example.js

var x = 5;
var addX = function(value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

index.js

var example = require('./example.js');

console.log(example.x); // 5
console.log(example.addX(1)); // 6

CommonJS模块的特点:

所有代码都运行在模块作用域,不会污染全局作用域。 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。 模块加载的顺序,按照其在代码中出现的顺序。

require内部处理流程

require 实际是 指向当前模块的 module.require, module.require 又调用Node的 Module._load(此Module非彼module)

Module._load = function(request, parent, isMain) {
  // 1. 检查 Module._cache,是否缓存之中有指定模块
  // 2. 如果缓存之中没有,就创建一个新的Module实例
  // 3. 将它保存到缓存
  // 4. 使用 module.load() 加载指定的模块文件,
  //    读取文件内容之后,使用 module.compile() 执行文件代码
  // 5. 如果加载/解析过程报错,就从缓存删除该模块
  // 6. 返回该模块的 module.exports
};

其中 module.compile()执行如下:

Module.prototype._compile = function(content, filename) {
  // 1. 生成一个require函数,指向module.require
  // 2. 加载其他辅助方法到require
  // 3. 将文件内容放到一个函数之中,该函数可调用 require
  // 4. 执行该函数
};

这是大概的CommonJS 流程 详见CommonJS规范

AMD(异步模块定义)

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。

CommonJS 采用的是同步加载机制,如果用于 客户端,必定受到网络的限制。所以,CommonJS不 适用于客户端。 而 AMD 采用的是 模块异步加载 方式,在需要执行到模块文件的时候,实现异步加载,回调执行。 看例子:

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

当执行到这一段代码的时候, 浏览器会先 加载 math 模块,在math模块加载成功后, 再执行后面的回调函数 math.add(2,3)

require.js

说道AMD 就不得不提 require.js了。 因为目前要实现 AMD , 不要按照require要求的写法。 首先下载最新require.js ,然后在 html 底部写上如下代码:

<script src="js/require.js" data-main="js/main"></script>

data-main用于指定网页程序的主模块

main.js

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // some code here
  });

要加载的模块也必须使用特定的写法,使用define() moduleA.js

define(['moduleD'],function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });

CMD(通用模块定义)

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

CMDAMD 在使用方面非常相似。(其实我没用过)

知呼上的比较

对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码: 作者:玉伯 链接:https://www.zhihu.com/question/20351507/answer/14859415 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ... 
})

// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})

就是说, 模块加载完成后, AMD 是立刻执行的,而 CMD是在需要用到的时候才执行的 针对这些不同, 在体现上: AMD 速度会相对快, 但是会浪费资源 CMD 节省资源, 性能会差一点(反应时间)

webpack

react.jswebpack 流行起来。(至少我是通过 react.js 认识到 webpack 的) react.js 可以说是前端(浏览器)项目,可是在编程风格上,确实不折不扣的 CommonJS 风格。 webpack 兼容了 CommonJSAMD

webpack 是一个模块管理工具。 对于 CommonJS 的模块, 对将其 最终打包在一个js文件里面, 对于不写不需要立刻执行的文件,也可以拆分出来,在运行时异步加载。

当然, 这里并不打算 说明怎么使用 webpack , google上有很多丰富的教程。


巨人的肩膀上,加自己的一点感悟

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • js原生函数之call和apply,bind

    call 和 apply 和 bind 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。

    用户1394570
  • 利用canvas实现毛笔字帖(三)

    3. 第3部分controller.js 这一部分的功能就是要修改毛笔的颜色,还有清空画布。 功能简单,我们一起向下讲。 一开始依然是init controll...

    用户1394570
  • win7 安装 mac虚拟机

      一周前社团ios方向刚完成招新,图新鲜的我也试装了一下虚拟机。自己装的时候是按教程来的,很轻松就装成了。 ios的经理见我装的那么溜,就把几个需要装虚拟机的...

    用户1394570
  • JavaScript模块化-CommonJS、AMD、CMD、UMD、ES6

    AMD(Asynchronous Module Definition)异步模块定义,客户端规范。采用异步方式加载模块,模块加载不影响它后面语句的代执行。

    胡哥有话说
  • Python-模块与包的管理

    - 大大提高了代码的可维护性; - 编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用;

    py3study
  • Python学习,这有可能是最详细的PIL库基本概念文章了

    PIL有如下几个模块:Image模块、ImageChops模块、ImageCrackCode模块、ImageDraw模块、ImageEnhance模块、Imag...

    一墨编程学习
  • CommonJS 和 ES6 Module 究竟有什么区别?

    作为前端开发者,你是否也曾有过疑惑,为什么可以代码中可以直接使用 require 方法加载模块,为什么加载第三方包的时候 Node 会知道选择哪个文件作为入口,...

    coder_koala
  • 使用Maven的父项目,多个子模块来开发Springboot项目,新建的子模块如何和同级的子模块进行依赖

    1、业务场景,使用Maven来构建项目,创建一个父工程,然后创建多个子模块,子模块data-runtime模块作为启动模块,同时将前端界面放到该模块。这里需要注...

    别先生
  • 【AI白身境】搞计算机视觉必备的OpenCV入门基础

    它是一款由Intel公司俄罗斯团队发起并参与和维护的一个计算机视觉处理开源软件库。

    用户1508658
  • 浅谈Python中的模块

    为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个...

    砸漏

扫码关注云+社区

领取腾讯云代金券