前端模块化之AMD — Requirejs的使用

  1. 前言
  2. 模块化的好处
  3. 模块化规范
    1. AMD
    2. CMD
    3. ES6 Module
  4. require.js
    1. 一、初探
    2. 二、基本使用
    3. 三、简化
    4. 四、配置

本篇聊聊前端模的块化规范,其中比较常用的AMD规范以及其代表作requrie.js



前言

随着Ajax技术的兴起,前后端分离的开发模式逐渐占领了几乎整个市场,现在的服务器带宽也足够完成大量数据交互,于是很多以前在服务器端的逻辑也可以移植到前端来处理了,从而减轻服务器的压力,当然,这样的话Javascript代码就会越来越复杂。而Javascript作为一门松散的弱类型语言,在一个大型项目面前如果没有合理的拆分与规划,将会变得很难维护,这个时候我们就需要把前端逻辑做一个模块化的处理。

所谓模块化就是把需要重复使用的功能封装成模块,一个页面有一个统筹全局的对象把所有模块引入进来,最终形成一个产品,做成一个完整的项目。

JS本身在ES6以前没有模块化的,ES6有模块化了,但是主流浏览器对于ES6模块化的支持度不足,所以一般不能直接使用,所以我们今天讨论第三方的模块化实现。

模块化的好处

就好比要生产一台挖掘机,是由各个厂商提供的配件组装出来的,而不是由一家公司从头到尾生产,这样的好处是各个零部件各司其职,如果有一个功能坏掉了只需要找到对应的零部件解决问题即可,从而避免将来维修的麻烦。

作为代码也是同样的道理,一个完整的项目可以由很多个模块组成,如果某部分功能需要修改或者升级只需要找到对应模块的代码进行维护即可,大大提高了代码的可读性以及节约了维护成本。

模块化规范

模块的使用一般分为导入导出,定义一个模块需要导出出去在需要使用的地方导入。所谓模块化规范就是规定了模块的使用方式,不同的规范制定了不同的导入和导出的方式。常见的模块化规范有如下几种:

AMD

​ 依赖前置:提前引入,文件开头把需要的模块一次性全部引入,后面直接使用

​ 前期消耗比较大,后期执行效率很高

​ 代表作是 require.js

CMD

​ 按需加载:在代码执行过程当中需要一个模块了才去加载

​ 整个曲线比较平缓

​ 代表作是sea.js,但是现在已经很少使用了

ES6 Module

浏览器都还不支持,但是可以借助像webpack 这样的打包工具来实现打包,从而使浏览器可以运行代码。详细用法可参照我的另一篇文章 锋利的ES6 — Module

另外:服务器端Node.js遵循commonJS规范,module.exports 导出模块,require引入模块。

require.js

我们今天以require.js为例来说说前端模块化的使用。

一、初探

第一步我们需要引入require.js文件

1
<script src="https://requirejs.org/docs/release/2.3.6/minified/require.js"></script>

我们可以稍微查看一下文件的源代码:

出乎我们意料的是require一上来二话不说先声明了三个全局变量:requirerequirejs以及define,但是这样我们的方向也就很明确了,我们可以打印一下这三个值:

我们可以看到这是三个函数,而且requirerequirejs看起来非常相似,所以我们可以尝试打印一下:

1
console.log(require === requirejs) // true

这个结果毫无疑问是true,也就是说requirerequirejs是同一个函数,那么我们肯定喜欢用require 🤓🤓🤓

另外一个就是define,所以我们用requirejs其实用的就是requiredefine这两个函数,而且结合咱们之前说过的模块化就是定义模块使用模块,所以define就是用来定义模块而require是用来引入模块的。

二、基本使用

比如我们定义一个a模块,a.js的代码可以如下:

1
2
3
4
5
6
7
8
9
10
11
12
// module a
define(() => {
class A {
constructor (name) {
this.name = name
}
say () {
console.log(this.name)
}
}
return A
})

再定义一个b模块,b.js代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
// module b
define(() => {
class B {
constructor () {
this.name = 'module b'
}
say () {
console.log(this.name)
}
}
return new B()
})

这里定义了一个类并分别return了这个类或者它的实例,这样我们在需要的时候就可以在需要使用的页面,比如与之同级的index.js中使用require函数来引入了:

1
2
3
4
5
require(['./a', './b'], (ModuleA, mB) => {
console.log('index page code')
new ModuleA('a').say()
mB.say()
})

我们通过require可以依次引入我们所需要的模块,并且在回调函数里按顺序接收各自模块的返回值来使用,这样就使得代码可以非常方便的完成服用,实现模块化了。

三、简化

现在我们在页面中需要写两个script标签,一个用来引入require.js,另外一个用来引入当前页面所需要的js,这样还是比较麻烦,require.js给我们提供了更简单的方式,我们可以在引入require.jsscript中写一个data-main属性,如下:

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

这样就可以少写一个script标签,因为require.js会帮助我们找到当前script标签上的自定义属性data-main并且根据属性值找到文件运行。

四、配置

现在模块化已经具有一定规模了,但是在正式项目中文件路径通常是比较复杂的,所以每次要依赖某个模块都写路径的方式比较麻烦,因此我们可以将所有模块做一个简单的配置,我们可以新建一个config.js,假设我们的项目路径如下:

在这个文件里我们可以集中将所有模块以及其路径做配置如下:

1
2
3
4
5
6
7
8
require.config({
baseUrl: '/', // 当前项目跟路径,可能需要视具体情况稍做调整
paths: {
// 模块名: '路径' // 注意:路径一定不能有后缀
a: 'js/a',
b: 'js/b'
}
})

这样我们可以修改一下index.js

1
2
3
4
5
6
7
require(['./config'], () => {
require(['a', 'b'], (ModuleA, mB) => {
console.log('index page code')
new ModuleA('a').say()
mB.say()
})
})

这样做的好处是现在引入模块不用写路径了,而是直接使用在config.js里配置好的模块名即可,简单高效。


代码不是万能的,但不写代码是万万不能的

Dary记


  • 更多干货,尽在公众号



转载请注明来源,文末有原始链接。欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 dary1112@foxmail.com

创作不易,您的打赏是我更新的动力

  • 支付宝

  • 微信

文章标题:前端模块化之AMD — Requirejs的使用

文章字数:1.7k

本文作者:Dary

发布时间:2020-07-13, 23:35:00

最后更新:2020-07-31, 17:55:33

原始链接:http://www.xiongdalin.com/2020/07/13/AMD-requirejs/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录