前端模块化 --AMD/RequireJs初识


I am a sucker for all beauty

参考链接

菜鸟:https://www.runoob.com/w3cnote/requirejs-tutorial-2.html

某位大佬:http://laichuanfeng.com/work/require-config-global/

前言

本菜鸟对于前端模块化的概念一直是比较模糊。学webpack也是稀里糊涂,自从webpack出现后,RequireJs几乎退出了人们的视野,官网也不再升级版本,后续出现的框架如angular、React、Vue又将前端模块上升到了另外一个高度。跟随前端时代的变迁固然重要,但有时,尝试一些“老技术”也无可厚非,或许也能给我们带来不同的体会。

RequireJS

一、目的

先明确AMD和RequireJS的关系:

AMD-异步模块定义

AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。AMD是一个组织,RequireJS是在这个组织下自定义的一套脚本语言。

作为js文件加载器,能运行在所有js环境中(如node)。

所以,AMD有什么意义?

(1)实现js文件的异步加载,避免网页失去响应

如下代码alert执行的时候,html内容是一片空白的,这就是js阻塞浏览器渲 染导致的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
index.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="a.js"></script>
</head>
<body>
<span>body</span>
</body>
</html>


a.js:
(function(){
function fun1(){
alert("it works");
}

fun1();
})()

(2)管理模块之间的依赖性,便于代码的编写和维护

如下一坨

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript" src="c.js"></script>
<script type="text/javascript" src="d.js"></script>
<script type="text/javascript" src="e.js"></script>
<script type="text/javascript" src="f.js"></script>
<script type="text/javascript" src="g.js"></script>
<script type="text/javascript" src="h.js"></script>
<script type="text/javascript" src="i.js"></script>
<script type="text/javascript" src="main.js"></script>

如果一个文件需要依赖另外一些文件中定义的东西时,这个文件依赖的所有文件都要在它之前导入。过于复杂的系统,依赖关系可能出现相互交叉的情况,依赖关系的管理就更加难了。例如main.js用到了前面a、b、c、d、e、f模块,但并未被其它模块使用,故可以且必须放到末尾导入。要确保模块的依赖在该模块导入之前就要导入,为了解除导入顺序的限制,只能让各模块间解耦。另外,加载文件越多,网页失去响应的时间就会越长。

二、使用

2.1 下载

2.1.1 链接下载

使用require.js的第一步,是先去官方网站下载最新版本。

2.1.2 npm

根目录下 输入

npm install requirejs --save-dev

如果当前目录没有package.json

npm init

2.2使用

目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
index.html
<script type="text/javascript" src="js/lib/require.js"></script>
<script type="text/javascript">
require(["js/script/a"]);
</script>

a.js
define(() => {
function f1() {
alert('it works');
}

f1();
});

so,页面内容能正常显示了。

基本API:

define, require, requirejs,其中require === requirejs。

define() – 定义一个模块,如上面的a.js

require() – 加载模块,并执行加载后的回调函数

注意:

第一个参数是个数组,即使只有一个模块,也必须以数组形式作为参数。

require中加载模块不能加.js后缀

1
2
3
require(["js/a"],function(){
alert("load finished");
})

加载文件:

require除了可以加载如上的本地模块,还可以加载来自本地服务器、其他网站、CDN的js文件。这时候就要配置require.config

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript" src="./js/lib/require.js"></script>
<script type="text/javascript">
require.config({
paths: {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"],
"a": "js/script/a"
}
});
//require(["js/script/a"]);
require(["jquery", "a"], $ => {
$(() => alert("load finished"));
});
</script>

通过paths,我们可以简化模块的名字。除此之外,paths还有一个重要功能,

如下代码,当百度的jquery没有加载成功后,会加载本地js目录下的jquery。

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript" src="./js/lib/require.js"></script>
<script type="text/javascript">
require.config({
paths: {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/lib/jquery"],
"a": "js/script/a"
}
});
//require(["js/script/a"]);
require(["jquery", "a"], $ => {
$(() => alert("load finished"));
});
</script>

上面require回调中的$参数,是依赖的jquery模块的输出变量,如果你依赖多个模块,可以依次写入多个参数来使用:

1
2
3
4
5
require(["jquery","underscore"],function($, _){
$(function(){
_.each([1,2,3],alert);
})
})

全局配置

requirejs提供了一种叫”主数据”(data-main)的功能

按照data-main的方式进行全局配置对于我这种菜鸡感觉真的不友好(wuwuwu,为什么jquery一直加载不了啊),所以我在网上找了一个适合我的解决方案,目前是可以加载成功的。

项目结构如下:

require.config.js为全局配置:

index.html中引入脚本方式:

解释(个人理解):require.config.js中的脚本只是一个配置,而不是加载,所以需要在config.js模块加载完成(保证全局配置生效后)再根据require.config()的配置去加载需要的模块。emmm…虽然方法很笨…但是至少不会出现下面的情况:

-------------要说再见啦感谢大佬的光临~-------------