使用基于 AMD 的 RequireJS 写一个花活项目
最近在研究前端模块化,大多数文章都提到了 AMD,关于 AMD 的模块标准(或者说规范)讲的都很清楚,什么异步加载、保证正确顺序,对付八股很够,但是唯独没有关于 AMD 的实操工程,大多数是纸上谈兵,所以经过我的博览群书(其实是翻垃圾桶,十个九个抄)终于找到了在 AMD 那个年代的工程和一些简单实现)
AMD
AMD(Asynchronous Module Definition) - 异步模块定义,AMD 是一个模块规范(或者说标准),它其实是 CommonJS 规范的分支,这也就是为什么很多文章里提到 CommonJS 时往往会带上 AMD
定义
使用 AMD 规范的模块要求如下
define(id?, dependencies?, factory);
id是名称dependencies是依赖factory是模块逻辑
以上仅为简述,完整的 AMD 介绍请参考文档
实现
规范只是理论而不是实现,像 CommonJS 规范就有很多实现,其中最出名的就是 Node.js,还有比较经典的理论和实现的例子有 Promise A+ 规范和一系列的 Promise 实现,比如浏览器的 ES6 Promise 原生实现、开源实现 kriskowal/q...,而 AMD 的实现就是在 2009 年 2 月的推出的 RequireJS
文章例子就是基于 RequireJS 的工程实现
RequireJS 的使用
RequireJS 源于 CommonJS 但后面又从其中独立出去成立了新社区,因此没有和 CommonJS 的实现 Node.js 及其生态(npm)产生太多联系,也就是说 RequireJS 的项目是不需要 Node.js 环境的
文章使用的是 require.js@2.3.6
文章实现的是通过 JS 传递颜色名称并将对应的十六进制颜色渲染到 DOM 中,其中文件结构
├── app - 项目代码
| ├── utils.js - 工具模块
| └── main.js - 主逻辑
├── lib - 第三方库
| ├── draw-dom.js
| └── require.js
├── app.js - 入口文件(包含 require.js 的配置)
├── index.html
目录结构基于 RequireJS 官网给出的文档中的单页应用的例子(2011 年就有单页应用的说法了!)
<!-- index.html -->
<head>
<script data-main="app.js" src="lib/require.js" async></script>
</head>
<body>
<h1 id="app">amd-learning</h1>
</body>
入口
入口文件主要是配置 require.js 和加载入口函数
// app.js
require.config({
baseUrl: "lib",
paths: {
app: "../app",
},
});
require(["app/main"]);
baseUrl用于指定第三方模块的位置,后期在主逻辑中可以直接通过名称调用,比如lib目录下的draw-dom模块require(draw-dom)paths用来指定用户自定义模块,即源代码部分
自定义模块
目录中的 utils 就是自定义模块,在主逻辑中可以根据相对路径去引用,这一点和 CommonJS 保持一致
define(function (require) {
const drawDOM = require("draw-dom");
const utils = require("./utils");
drawDOM.draw("app", utils.translate("red"));
});
注意,在引用模块时必须使用 require,而 require 由 define 函数的参数传入(这是 require.js 的默认模块)
而自定义模块导出可以选择返回一个对象作为导出值
如果工厂函数返回一个值(一个对象、函数或任何 Truthy 值),那么该值应该被分配为模块的导出值
如下
// utils.js
define(function () {
return {
translate: function (name) {
let color = "";
switch (name) {
case "red":
color = "#FF0000";
break;
default:
color = "#000000";
}
return color;
},
};
});
第三方模块
require.js 使用的模块需要在模块源码提供处下载,此处放置在 lib 目录统一管理,为了便于描述我直接手撸了一个
define("draw-dom", ["exports"], function (exports) {
exports.draw = function (id, color) {
document.querySelector(String("#" + id)).style.color = color;
};
});
注意,导出可以使用 exports 模块(exports 和 require 一样都是 require.js 的默认模块)
最后例子的运行效果如下

参考资料
转载自:https://juejin.cn/post/7179631517621026875