Learn X in Y minutes 深度解析:AMD 异步模块定义——从 define/require 到 require.js 与 r.js 构建优化
文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载AMDAsynchronous Module Definition异步模块定义是 JavaScript 模块化体系中最早面向浏览器异步加载场景的规范之一。本文以 learnxinyminutes-docs 仓库中收录的 AMD 教程英文原版 及 印地语译本为骨架系统讲解define/require双方法模型、require.js 的真实世界用法以及 r.js 的整项目构建优化流程。读完本文你将能独立读懂并写出 AMD 风格模块配置baseUrl与paths路径映射并通过r.js将开发期分散的多文件模块打包为生产环境可用的单文件脚本。AMD 是什么为浏览器而生的异步模块规范Asynchronous Module DefinitionAPI 规定了一种定义 JavaScript 模块的机制模块自身及其依赖可以被异步加载。这一点对浏览器环境尤其重要——在浏览器中模块的同步加载会带来四类典型问题性能performance同步加载会阻塞后续脚本解析与页面渲染可用性usability页面交互会被漫长的脚本下载阻塞调试debugging脚本加载顺序出错时依赖缺失的错误极难定位跨域访问cross-domain access同步脚本引用受同源策略限制难以从 CDN 或其他域加载模块。AMD 正是为解决这些问题而设计的模块定义规范。整个 API 的核心极度精简——只有两个方法define与require。所有模块的定义definition与消费consumption都围绕它们展开// define(id?, dependencies?, factory) 定义一个模块 // require(dependencies, callback) 导入一组依赖 // 并在传入的回调中消费它们基础概念define 与 require 双方法模型用 define 定义无依赖的具名模块先看最基础的用法用define定义一个具名模块named module它没有任何依赖只需传入模块名和工厂函数factorydefine(awesomeAMD, function(){ var isAMDAwesome function(){ return true; }; // 工厂函数的返回值就是其他模块或 require 调用 // 在请求 awesomeAMD 模块时接收到的导出值。 // 导出值可以是任何东西构造函数、普通对象、 // 原始类型甚至是 undefined虽然这没什么用。 return isAMDAwesome; });关键点在于工厂函数的返回值即模块的导出值。无论你导出的是构造函数、对象、原始值还是undefined其他模块拿到的就是这个值本身。定义带依赖的模块现在定义一个依赖awesomeAMD的新模块。注意define调用中多了一个参数——依赖数组define(loudmouth, [awesomeAMD], function(awesomeAMD){ // 依赖会按照声明顺序依次传给工厂函数的形参 var tellEveryone function(){ if (awesomeAMD()){ alert(This is sOoOo rad!); } else { alert(Pretty dull, isn\t it?); } }; return tellEveryone; });这里体现了 AMD 的两个核心约定依赖即参数[awesomeAMD]中声明的依赖会按顺序映射为工厂函数的形参awesomeAMD依赖先解析后执行工厂函数只有在全部依赖就绪后才会被调用。用 require 启动程序知道了如何定义模块接下来用require启动程序。require的签名是(arrayOfDependencies, callback)require([loudmouth], function(loudmouth){ loudmouth(); });require负责导入依赖集合并把它们作为参数传入回调。当页面加载完成后loudmouth被调用弹出 This is sOoOo rad!。一个极简的 AMD 实现30 行看懂原理为了让教程真正可运行原文档当场实现了一个非异步的 AMD 精简版本。这个实现虽然只有两个函数却完整揭示了 AMD 的底层机制——模块注册表 依赖注入function define(name, deps, factory){ // 注意无依赖模块的处理方式 // 没有 factory 时第二个参数deps本身就是工厂函数 define[name] require(factory ? deps : [], factory || deps); } function require(deps, callback){ var args []; // 首先取出 require 调用所需的全部依赖 for (var i 0; i deps.length; i){ args[i] define[deps[i]]; } // 满足回调的全部依赖后注入并调用 return callback.apply(null, args); }这段代码揭示了 AMD 的实质define把模块名作为键、工厂函数的执行结果作为值存入模块注册表require遍历依赖数组从注册表中按名取回已解析的模块再通过callback.apply(null, args)把依赖注入回调无依赖模块的巧妙处理factory ? deps : []即没有工厂函数时直接取deps作为工厂。这也是官方规范amdjs/amdjs-api所描述的通用模型一个模块注册表 一个依赖解析注入器。真实加载器如 require.js只是在这个模型之上补上了异步加载层。实战require.js 中的真实世界用法XHR 异步加载AMD 中的 A 被真正实现与上面的入门示例不同require.js最流行的 AMD 库真正实现了 AMD 中的A——通过 XHR 异步加载模块及其依赖/* file: app/main.js */ require([modules/someClass], function(SomeClass){ // 回调会被延迟执行直到依赖加载完成 var thing new SomeClass(); }); console.log(So here we are, waiting!); // 这行会先执行注意执行顺序console.log在回调之前执行。这正是异步加载的直观证据——require发出 XHR 请求后立刻返回页面脚本继续往下走当modules/someClass从服务器返回并解析完毕后回调才被触发。约定优于配置一文件一模块路径即模块名按照惯例通常一个文件存放一个模块。require.js 能基于文件路径解析模块名因此你不需要给模块命名直接用文件位置引用即可。以下面目录结构为例someClass被假定位于baseUrl配置所指向的modules文件夹中app/ main.js modules/ someClass.js someHelpers.js ... daos/ things.js ...这意味着我们可以不指定模块 id就定义someClass/* file: app/modules/someClass.js */ define([daos/things, modules/someHelpers], function(thingsDao, helpers){ // 模块定义同样是异步完成的 function SomeClass(){ this.method function(){/**/}; // ... } return SomeClass; });依赖数组里的daos/things、modules/someHelpers都是相对baseUrl的路径加载器会据此发起 XHR 请求。requirejs.config自定义路径映射要修改默认的路径映射行为在main.js中调用requirejs.config(configObj)/* file: main.js */ requirejs.config({ baseUrl : app, paths : { // 也可以从其他位置加载模块 jquery : //ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min, coolLibFromBower : ../bower_components/cool-lib/coollib } }); require([jquery, coolLibFromBower, modules/someHelpers], function($, coolLib, helpers){ // main 文件必须至少调用一次 require // 否则任何代码都不会被执行 coolLib.doFancyStuffWith(helpers.transform($(#foo))); });配置项语义如下配置项作用示例值baseUrl所有模块路径解析的基准目录apppaths为模块 id 指定实际加载路径可用完整 URL如 CDN或相对baseUrl的路径jquery : //ajax.googleapis.com/...、coolLibFromBower : ../bower_components/...特别值得注意paths的两种取值跨域 URLjquery直接指向 Google CDN 的压缩包路径省略.js后缀异步加载天然绕开了同步脚本的跨域限制本地相对路径coolLibFromBower指向baseUrl之外的 bower 组件目录用../跳出app目录。data-main单一入口自动加载基于 require.js 的应用通常只有一个入口main.js它作为data-main属性传给require.js的 script 标签页面加载时会自动加载并执行!DOCTYPE html html head titleA hundred script tags? Never again!/title /head body script srcrequire.js>$ npm install requirejs -g然后用配置文件喂给它$ r.js -o app.build.js-o表示 optimizer 模式app.build.js即构建配置文件。app.build.js 配置详解针对上文示例构建配置大致如下/* file : app.build.js */ ({ name : main, // 入口模块的名称 out : main-built.js, // 输出文件的名称 baseUrl : app, paths : { // empty: 告诉 r.js这个模块仍然从 CDN 加载 // 使用 main.js 中指定的位置不要打进构建产物 jquery : empty:, coolLibFromBower : ../bower_components/cool-lib/coollib } })配置项含义name入口模块名即依赖图分析的起点out构建产物文件名baseUrl与main.js中的baseUrl保持一致供模块路径解析paths与运行时配置对应其中empty:前缀是关键技巧empty:前缀的语义值得单独强调以jquery : empty:为例r.js 会跳过该依赖的本地解析与合并构建产物中保留对main.js指定 CDN 地址的引用。这样既避免了把体积庞大的第三方库打进产物又保持了开发期引用路径 生产期引用路径的一致性。生产环境切换只改一行>script srcrequire.js>赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐学习 AMD 异步模块定义从 define/require 到 require.js 与 r.js 构建实战学习 AMD 异步模块定义从 define/require 到 require.js 与 r.js 构建实战 导读 本篇技术指南以本仓库根目录的 amd.md文档教程AMD 异步模块定义实战指南基于 learnxinyminutes-docs 的 define/require 与 require.js 全解析AMD 异步模块定义实战指南基于 learnxinyminutes docs 的 define/require 与 require.js 全解析 本指南以仓库文档教程Learn X in Y Minutes 项目文档Learn X in Y Minutes 项目文档 1. 项目目录结构及介绍 learnxinyminutes docs 项目是一个开源文档项目旨在为各种编程文档教程上一篇KMS智能激活工具终极指南5分钟永久解决Windows和Office激活难题下一篇AI语音转换的终极实战指南检索机制驱动的商业级语音合成解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

LLDAP 数据库后端迁移实战:从 SQLite 平滑切换至 PostgreSQL / MySQL / MariaDB

LLDAP 数据库后端迁移实战:从 SQLite 平滑切换至 PostgreSQL / MySQL / MariaDB

后端认证鉴权 【免费下载链接】lldap Light LDAP implementation 项目地址: https://gitcode.com/gh_mirrors/ll/lldap 点击查看 免费下载 LLDAP 是一款轻量级 LDAP 实现,其数据默认存储在 SQLite 数据库中,适合中小规模部署;但当…

2026/11/15 17:43:36 阅读更多 →
ts-jest 自定义 AST Transformer 完全指南:astTransformers 配置、编写与实战

ts-jest 自定义 AST Transformer 完全指南:astTransformers 配置、编写与实战

测试开发工具 【免费下载链接】ts-jest A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript. 项目地址: https://gitcode.com/gh_mirrors/ts/ts-jest 点击查看 免费下载 astTransformers 是 ts-jest 提供…

2026/11/10 8:06:44 阅读更多 →
90DaysOfDevOps Day 83:Grafana 数据可视化实战——基于 kube-prometheus 与 Prometheus Operator 部署监控面板

90DaysOfDevOps Day 83:Grafana 数据可视化实战——基于 kube-prometheus 与 Prometheus Operator 部署监控面板

文档/教程 【免费下载链接】90DaysOfDevOps This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Pri…

2026/11/10 8:06:44 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/15 5:13:35 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/15 5:13:35 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/15 5:13:35 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/15 3:37:41 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/15 4:18:38 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/15 5:13:35 阅读更多 →

日新闻

周新闻

月新闻