WEB 前端模块化方案完全总结

(function(global){

// code

})(this);

CJS,CommonJS 模块规范


CommonJS 是 nodejs 广泛使用的模块化机制。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

  • Nodejs 基本上按照 CommonJS 规范实现了模块系统,不过还是略有差异,因此是一种变体。

  • CommonJs 规定每个 js 文件都能被看作是一个模块,其内部定义的变量是私有的,不会对外暴露,不会污染全局。

  • CommonJs 采用同步(一个接着一个)的加载模块,适用于服务器,不适合在浏览器端使用。

  • CommonJs 不被浏览器端支持,因为浏览器没有 module, exports, require, global 四个环境变量。如果要在浏览器使用 CommonJs,需要使用工具转换(browserify)。

CommonJS 主要有以下方式对模块进行导入导出:

module.exports = { a: 12, foo: function(){ console.log(this.a) } }

//导出为一个对象

var obj = require(‘./m1.js’)

obj.a = 34

obj.foo()

module.exports = function(){ return {a: 12} }

//导出是一个函数, 可以直接执行

var foo = require(‘./m2.js’)

foo()

exports.foo = function(){ return {a: 12}}

//导出为一个对象, 对象里面的属性为foo

var obj = require(‘./m3.js’)

obj.foo()

注意:不要使用 import,import 是 ES6 的语法。想要在浏览器环境中使用,需要在 index.js 中将模块导入,然后 node 使用如下命令:

browserify index.js -o bundle.js

前提是安装了 browserify 这个包,然后在 html 里面引入 bundle.js 即可。

AMD,CMD,异步模块定义


AMD

不同于 CommonJs,AMD 是异步加载,名称就是 Asynchronous Module Difinition,允许指定回调函数,等异步加载完成之后即可调用回调函数。AMD 的核心思想就是通过 define 来定义模块,然后通过 require 来加载模块,它依赖于 require.js,在 html 文件里面引入 script:

定义模块 m1

define([模块名称], [依赖模块], function(){

name: ‘vey-module-1’,

getName: function(){

return name

}

return {getName: getName}

})

上面的模块名称定义此模块的名称,不写则默认为文件名去掉后缀。依赖模块指定此模块依赖的模块,类型为数组。此模块的内容定义在 function 里面。

再定义一个模块 m2

define([‘m1’], function(m1){

name: ‘vey-module-2’,

function show() {

console.log(name, m1.getName())

}

return { show }

})

定义 index.js

(function(){

// 配置模块的路径

require.config({

paths: {

m1: ‘./m1’

m2: ‘./m2’

}

})

require([‘m2’], function(m2){

m2.show()

})

})()

然后就可以看到执行结果了。

AMD是依赖前置的,即不管你用没用到,只要你设置了依赖就会去加载,不是按需加载的。

上面的代码在浏览器里运行,会先后发生这些事情:

  • 它首先根据指定的require.js加载require.js

  • 加载完成后,require.js会在所有的 script 标签里寻找 data-main 属性指定的路径文件作为下一个将要加载的脚本,在这里,就是./index.js

  • 开始加载./index.js,加载后,解析并执行它,如果发现它有其他依赖,那么先加载所有的依赖(递归)并完成后,再执行./index.js里面 require 的回调函数;

页面就绪后,我们可以在渲染后的 DOM 树中看到<head>标签里多了几个<script>元素,require.js正是通过这些标签来加载相应的 AMD 模块文件的。

CMD

相比 AMD,CMD 也同样是异步加载,AMD 是依赖前置,CMD 是就近加载,按需加载的。主要产物就是sea.js

SeaJS 最初以就近加载以及支持加载 CSS 等特点吸引了很多用户,并提出了 CMD 规范。但在 RequireJS 也支持这些特性之后渐渐淡出,虽然 SeaJS 没有明显的缺点,但统一标准未尝不是一件好事。

sea.js核心思想与 AMD 高度类似,通过 define 定义模块,require 加载模块,如下:

定义 m1

define(function (require, exports, module) {

var msg = ‘m1’

function foo() {

console.log(msg);

}

module.exports = {

foo

}

})

定义 m2

define(function (require, exports, module) {

var msg = ‘m2’

function bar() {

console.log(msg);

}

module.exports = bar

})

定义 m3

define(function (require, exports, module) {

var msg = ‘m3’

function fun() {

console.log(msg);

}

exports.fun = fun

})

定义 m4

define(function (require, exports, module) {

var msg = ‘m4’

var m2 = require(‘./m2’)

m2()

require.async(‘./m3’, function(m3){

m3.fun()

})

function func () {

console.log(msg)

}

exports.func = func

})

定义 index.js

define(function (require, exports, module) {

var m1 = require(‘./m1’)

m1.foo()

var m4 = require(‘./m4’)

m4.func()

})

UMD


鉴于存在 CommonJS、AMD 等不同的模块系统,为了让代码能够同时支持它们,社区提出了一种统一模块定义(Universal Module Definition,UMD)来解决不兼容的问题。所以,UMD 其实不是什么标准,可以看成是 IIFE amd + cjs 的兼容版。也就是一个 js 文件,可以用 script 标签引用加载,用 RequireJS 加载,也可以在 node 当成 CommonJS 模块加载。

一个常见的 UMD 模块声明实际上是一个立即执行函数表达式。模块的主体在一个工厂方法里面,其返回值作为模块最终暴露的对象。例如下面的模块暴露了一个构造函数 Time:

(function (global, factory) {

typeof exports === ‘object’ && typeof module !== ‘undefined’ ? module.exports = factory() :

typeof define === ‘function’ && define.amd ? define(factory) :

global.Time = factory();

}(this, function () {

// 模块工厂方法开始

‘use strict’;

var _private = ‘’;

function Time(param) {

this._date = new Date(param);

}

return Time;

// 模块工厂方法结束

}));

以上原理其实很简单,因为通常如果一个变量在取右值时未定义,会发生引用错误(Reference Error),例如:

// 标识符 an_undefined_token 不在当前作用域链上

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-O8PNVQTV-1715706660164)]

[外链图片转存中…(img-8E8ShITE-1715706660164)]

[外链图片转存中…(img-P29deRXz-1715706660165)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值