在JavaScript应用中实现延迟加载的方法
本文详解如何利用RequireJS框架解决JavaScript应用中的性能瓶颈与代码耦合问题。通过对比传统直接引用方式,展示如何使用data-main指定入口、define定义依赖及require加载模块。重点解析Order与Customer模块的分离过程,实现按需加载,从而提升应用加载速度与可维护性。
引言与问题背景
无论是简单的还是复杂的Web应用,其基础构成通常包括HTML、JavaScript和CSS文件。开发者常借助JQuery、Knockout、Underscore等第三方JavaScript框架来提升开发效率。鉴于这些框架针对特定场景经过验证,直接采用它们比从零构建功能更为高效。然而,随着应用复杂度的增加,编写整洁、低耦合且易于维护的代码变得至关重要。本文将阐述如何利用RequireJS框架帮助开发者构建更模块化的代码,并通过延迟加载JavaScript文件来优化应用性能。首先,我们将展示不使用RequireJS的情况,随后在后续章节中演示如何使用RequireJS对其进行重构。
以下HTML页面包含一个id为“message”的<p>元素。当用户访问该页面时,系统将展示订单ID和客户姓名信息。
Common.JS文件定义了两个模块:Order和Customer。showData函数与页面body结合,通过调用write函数将输出信息插入页面。作为示例,showData函数中硬编码了ID为1,客户姓名为Prasad。
<!DOCTYPE html>
<html>
<head>
<title>JavaScript NonRequireJS</title>
<script src="common.js" type="text/javascript"></script>
</head>
<body>
<strong>Display data without RequireJS</strong>
<p id="message" />
<script type="text/javascript">
showData();
</script>
</body>
</html>
Common.JS
function write(message) {
document.getElementById('message').innerHTML += message + '</br>';
}
function showData() {
var o = new Order(1, "Prasad");
write("Order Id : " + o.id + " Customer Name : " + o.customer.name);
}
function Customer(name) {
this.name = name;
return this;
}
function Order(id, customerName) {
this.id = id;
this.customer = new Customer(customerName);
return this;
}
在浏览器中打开该页面,您将看到如下信息展示。

传统方式存在的问题
尽管上述代码能够正常显示输出,但仍存在以下问题:
- Common.JS文件包含了所有需要定义的函数(write、showData),且Order和Customer模块难以维护和复用。如果其他页面需要复用write函数并引用了该JavaScript文件,则不可避免地会导入该页面可能并不需要的其他函数和模块。
- Order模块(在面向对象编程中可视为“类”)在初始化过程中创建了一个Customer模块的实例。这意味着Order模块依赖于Customer模块。这种模块间的紧耦合使得未来在优化、重构和维护代码时面临较大困难。
- 每当客户端请求该页面时,Common.JS文件就会被载入DOM。在上述示例中,尽管我们仅需在页面上输出信息,但仍将不需要的模块(Customer、Order)加载到了内存中。加载不必要的应用资源(如JavaScript、CSS、图片文件等)会降低应用的整体性能。
- 虽然Common.JS文件中的模块可以被分离到不同的JavaScript文件中,但随着应用变得越来越复杂,判断JavaScript文件之间的依赖关系以及确定文件的加载顺序变得非常困难。
RequireJS框架负责处理JavaScript文件间的依赖关系,并根据需要按顺序加载它们。
使用RequireJS进行重构
使用RequireJS搭建应用
现在让我们查看重构后的代码。以下HTML代码引用了Require.JS文件。data-main属性定义了该页面的唯一入口点。在此场景中,它指示RequireJS在启动时加载Main.js。
<!DOCTYPE html>
<html>
<head>
<title>JavaScript RequireJS</title>
<script src="Require.Js" type="text/javascript" data-main="Main.js"></script>
</head>
<body>
<strong>Display data using RequireJS</strong>
<p id="message" />
</body>
</html>
Main.JS
由于该文件已通过data-main属性指定,RequireJS会尽快加载它。此文件利用RequireJS框架的函数来确定并定义对其他JavaScript文件的依赖关系。在以下代码片段中,第一个参数表示依赖关系(依赖Order.JS文件),第二个参数是一个回调函数。RequireJS分析所有依赖关系并载入它们,然后执行该回调函数。请注意,第一个参数的值(Order)必须与文件名(Order.JS)一致。
require(["Order"], function (Order) {
var o = new Order(1, "Prasad");
write(o.id + o.customer.name);
});
Order.JS
RequireJS框架提供了一种简便的途径来定义和维护JavaScript文件间的依赖关系。以下代码中的define函数声明了Customer.JS必须在处理Order回调函数之前载入。
define(["Customer"],
function (Customer) {
function Order(id, custName) {
this.id = id;
this.customer = new Customer(custName);
}
return Order;
}
);
Customer.JS
该文件不依赖于任何其他JavaScript文件,因此define函数的第一个参数值为空数组。
define([],
function () {
function Customer(name) {
this.name = name;
}
return Customer;
}
);
现在,请用浏览器打开该应用,您将看到如下输出。需要注意的是,RequireJS仅加载了必需的JavaScript文件。

总结
总结
在本文中,我们分析了RequireJS框架如何处理JavaScript文件间的依赖关系并根据需要载入它们。它能够帮助开发者编写更松耦合、更模块化且更具可维护性的代码。
谢谢
下载源代码: Lazy Loading using RequireJS (Prasad Honrao, Codetails)
core-js v2 迁移到 v3 的破坏性变更与注意事项
2026-11-05 18:10:26
JavaScript中%是取余还是取模?与Math.floor实现的区别
2026-11-05 18:09:12
React中怎么不可变地删除JS数组元素
2026-11-05 18:06:01
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
