抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文学习了前端模块化工具RequireJS的基本原理和使用方式。

1 简介

1.1 介绍

RequireJS是基于AMD(Asynchronous Module Definition)规范实现的JS模块加载器,主要用于浏览器环境。

AMD规范采用异步方式加载模块,推崇依赖前置,模块会提前加载。

RequireJS解决了传统加载方式的依赖管理混乱、命名冲突、加载顺序不可控等问题。

RequireJS的出现早于ESM,是早期前端模块化开发的主流方案之一,与SeaJS并称前端模块化双雄。

1.2 背景

在传统的JS开发中,所有代码都写在一个或多个全局作用域中,容易造成以下问题:

  • 命名冲突
  • 文件依赖顺序难以维护
  • 代码难以复用和测试

模块化开发通过将代码拆分成独立、可复用的单元,解决了上述问题。

1.3 对比

前端模块化规范对比:

规范 特点描述
AMD 异步加载,依赖前置,代表实现:RequireJS
CMD 异步加载,依赖就近,代表实现:SeaJS
CommonJS 同步加载,适用于服务端,代表实现:NodeJS
ESM 原生支持,静态编译,浏览器和服务端通用

2 快速使用

2.1 引入

下载使用依赖的require.js文件,提供了压缩版和注释版适用不同的使用环境:

目录结构:

code
1
2
3
4
5
6
7
webapp
├── index.html
└── js
├── require.js
├── require-main.js
└── show
└── show.js

在HTML中通过script元素引入:

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

使用data-main属性指定入口脚本的位置,入口脚本可以省略文件后缀,在加载依赖文件后,会自动加载入口脚本。

2.2 入口脚本

入口脚本也称为顶级脚本,入口脚本中定义了框架配置,加载入口脚本的方式属于异步加载。

如果不指定data-main属性,也可以手动加载:

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

如果需要在页面上执行require()方法,就不能使用异步加载的方式,因为在执行时入口脚本可能还没有加载,所以只能使用手动加载的方式。

2.3 定义模块

RequireJS官方文档建议一个JS文件只定义一个模块。

使用define()方法定义模块,需要在模块文件中定义。

示例:

show.js
1
2
3
4
5
6
7
8
define(function() {
function show(msg) {
console.log(msg);
}
return {
show: show
};
});

2.4 配置模块

通过require.config()定义框架配置,需要在入口脚本中定义。

示例:

require-main.js
1
2
3
4
5
6
require.config({
baseUrl: './js',
paths: {
'show': 'show/show'
}
});

2.5 使用模块

RequireJS默认所有模块都是脚本,因此使用模块时不需要指定.js后缀。

使用require()方法加载模块,可以在脚本文件中使用,也可以在页面中使用。

示例:

js
1
2
3
require(['show'], function(show) {
show.show('hello');
});

在页面使用时需要先加载入口脚本,才能使用模块。

3 高级用法

3.1 多种方式定义模块

3.1.1 无返回值

定义无返回值的模块并配置模块:

show.js
1
2
3
define(function() {
console.log('show');
});

使用show模块:

js
1
2
require(['show'], function() {
});

3.1.2 有返回值

定义有返回值的模块并配置模块:

show.js
1
2
3
4
5
6
7
8
define(function() {
function show(msg) {
console.log(msg);
}
return {
show: show
};
});

使用show模块:

js
1
2
3
require(['show'], function(show) {
show.show('hello');
});

3.1.3 模块依赖

定义show模块并配置模块:

show.js
1
2
3
4
5
6
7
8
define(function() {
function show(msg) {
console.log(msg);
}
return {
show: show
};
});

定义test模块并配置模块,在test模块中依赖show模块:

test.js
1
2
3
4
define(['show'], function(show) {
console.log('test');
show.show('hello');
});

使用test模块:

js
1
2
require(['test'], function() {
});

3.1.4 匿名模块

定义模块时没有指定模块名:

show.js
1
2
3
4
5
6
7
8
define(function() {
function show(msg) {
console.log(msg);
}
return {
show: show
};
});

匿名模块有两种使用方式:

  • 不在配置中定义模块名,在使用时将位置作为模块名使用:
    js
    1
    2
    3
    require(['show/show'], function(show) {
    show.show('hello');
    });
  • 在配置中定义模块名并指定位置,在使用时通过模块名使用:
    js
    1
    2
    3
    require(['show'], function(show) {
    show.show('hello');
    });

3.1.5 具名模块

定义模块时指定模块名,需要在第一个参数传入字符串:

show.js
1
2
3
4
5
6
7
8
define('show/show', function() {
function show(msg) {
console.log(msg);
}
return {
show: show
};
});

具名模块有两种使用方式:

  • 模块名就是文件所在位置,在使用时通过模块名使用:
    js
    1
    2
    3
    require(['show/show'], function(show) {
    show.show('hello');
    });
  • 模块名不是文件所在位置,需要在配置中定义模块名并指定位置,在使用时通过模块名使用:
    js
    1
    2
    3
    require(['show'], function(show) {
    show.show('hello');
    });

3.2 非AMD模块支持

3.2.1 配置

对于非AMD规范的库,比如早期的JQuery库,这些库并没有通过define()方法定义,并不是模块,所以需要对其进行特殊配置,以便作为模块使用。

配置path属性,增加JQuery库:

require-main.js
1
'jquery': 'jquery/jquery-1.6.4.min'

配置shim属性,增加JQuery库:

require-main.js
1
2
3
4
'jquery': {
deps: [],
exports: '$'
}

参数:

  • deps:表示依赖,单个依赖可以使用字符串,多个依赖需要使用数组,如果没有可以省略。
  • exports:表示导出对象的名称,如果没有可以省略。

如果只有deps属性,还可以进一步简写为:

require-main.js
1
'test': ['jquery']

3.2.2 使用

可以在页面上直接使用JQuery库:

js
1
2
3
require(['jquery'], function($) {
$('body').append('<p>jquery</p>');
});

也可以在test模块中依赖JQuery库:

test.js
1
2
3
define(['jquery'], function($) {
$('body').append('<p>test</p>');
});

然后在页面上使用test模块:

js
1
2
require(['test'], function() {
});

3.3 模块替换

3.3.1 多版本支持

通过map属性可以配置模块的多版本支持:

require-main.js
1
2
3
4
5
6
7
8
map: {
'*': {
'test': 'test-1.0'
},
'new/demo': {
'test': 'test-2.0'
}
}

在使用test模块时,默认使用test-1.0模块,如果是new/demo.js文件,则使用test-2.0模块。

3.3.2 模块映射

通过map属性可以配置模块映射:

require-main.js
1
2
3
4
5
map: {
'*': {
'css': 'js/css.min'
}
}

在依赖css模块时,会自动映射为js/css.min模块:

js
1
2
3
require(['css!css/min'], function(css) {
console.log(css);
});

先加载js/css.min模块,再加载css/min模块。

评论