摘要:說明內(nèi)容主要包括三部分按源碼的結(jié)構(gòu)順序?qū)λ械淖兞考胺椒ǖ恼f明運(yùn)行流程流程相關(guān)圖片一源碼的結(jié)構(gòu)為了方便比對源碼,按源碼的結(jié)構(gòu)順序展示。
說明:
內(nèi)容主要包括三部分:
1.按源碼的結(jié)構(gòu)順序 對 所有的變量及方法的說明
2.requirejs運(yùn)行流程
3、流程相關(guān)圖片
為了方便比對源碼,按源碼的結(jié)構(gòu)順序展示。
var requirejs, require, define; (function (global, setTimeout) { var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, version = "2.3.5", commentRegExp = //*[sS]*?*/|([^:""=]|^)//.*$/mg, //去除注釋 cjsRequireRegExp = /[^.]s*requires*(s*[""]([^""s]+)[""]s*)/g,//提取require函數(shù)的arguments jsSuffixRegExp = /.js$/, currDirRegExp = /^.//, op = Object.prototype, ostring = op.toString, hasOwn = op.hasOwnProperty, isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document), isWebWorker = !isBrowser && typeof importScripts !== "undefined", readyRegExp = isBrowser && navigator.platform === "PLAYSTATION 3" ? /^complete$/ : /^(complete|loaded)$/, defContextName = "_", isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]", contexts = {}, cfg = {}, globalDefQueue = [], useInteractive = false; //返回singlePrefix或空 function commentReplace(match, singlePrefix) {} //判斷函數(shù) function isFunction(it) {} //判斷數(shù)組 function isArray(it) {} //執(zhí)行函數(shù)func(ary[i], i, ary);返回真值,跳出循環(huán) function each(ary, func) {} //與each序列反 function eachReverse(ary, func) {} //判斷obj是否有prop function hasProp(obj, prop) {} //返回obj上的prop function getOwn(obj, prop) {} //循環(huán)調(diào)用func(obj[prop], prop);返回真值,跳出循環(huán) function eachProp(obj, func) {} //混合source屬性值(target沒有同名的)到target //force為真,target同名覆蓋,deepStringMixin為真,深混合 function mixin(target, source, force, deepStringMixin) {} //返回逆名函數(shù),執(zhí)行為obj調(diào)用fn函數(shù) function bind(obj, fn) {} //返回script元素的集合 function scripts() {} //throw err; function defaultOnError(err) {} //例getGlobal("aa.bb");為global.aa.bb function getGlobal(value) {} //生成一個(gè)錯(cuò)誤 function makeError(id, msg, err, requireModules) {} if (typeof define !== "undefined") { return; } if (typeof requirejs !== "undefined") { if (isFunction(requirejs)) { return; } cfg = requirejs; requirejs = undefined; } if (typeof require !== "undefined" && !isFunction(require)) { cfg = require; require = undefined; } function newContext(contextName) { var inCheckLoaded, Module, context, handlers, checkLoadedTimeoutId, config = { waitSeconds: 7, baseUrl: "./", paths: {}, bundles: {}, pkgs: {}, shim: {}, config: {} }, registry = {}, enabledRegistry = {}, undefEvents = {}, defQueue = [], defined = {}, urlFetched = {}, bundlesMap = {}, requireCounter = 1, unnormalizedCounter = 1; //ary中.刪除此項(xiàng);..刪此項(xiàng)和前一項(xiàng)除(i === 0 || (i === 1 && ary[2] === "..") || ary[i - 1]==="..") function trimDots(ary) {} //路徑處理.config.pkgs有name值優(yōu)先,無值按相對路徑轉(zhuǎn)化,apply是否啟用地圖配置 function normalize(name, baseName, applyMap) {} //刪除data-requiremoduley為name和data-requirecontext === context.contextName的script function removeScript(name) {} //先移除再加載模塊; function hasPathFallback(id) {} //第一個(gè)"!"分離的前后數(shù)據(jù) return [prefix, name]; function splitPrefix(name) {} //返回模塊的屬性對象 // return { // prefix: prefix, // name: normalizedName, // parentMap: parentModuleMap, // unnormalized: !!suffix, // url: url, // originalName: originalName, // isDefine: isDefine, // id: (prefix ? // prefix + "!" + normalizedName : // normalizedName) + suffix // }; function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {} //registry[id]有值取值,沒值生成新的context.Module對象,并賦給registry[id] function getModule(depMap) {} //模塊加載完且name為defined 或 加載出錯(cuò)且name為error ? 執(zhí)行fn : 模塊綁定事件 function on(depMap, name, fn) {} //errback ? 執(zhí)行errback(err) : mod.emit("error", err)執(zhí)行刪除操作 function onError(err, errback) {} //將globalDefQueue推入defQueue function takeGlobalQueue() {} //commonjs風(fēng)格 handlers = { //mod.require ? 返回mod.require : localRequire "require": function (mod) {}, "exports": function (mod) {}, "module": function (mod) {} }; //清除registry[id]、enabledRegistry[id] function cleanRegistry(id) {} //遞歸mod.depMaps,執(zhí)行mod.check(); function breakCycle(mod, traced, processed) {} //檢查加載狀態(tài),不同狀態(tài)執(zhí)行不同操作 function checkLoaded() {} Module = function (map) { this.events = getOwn(undefEvents, map.id) || {}; this.map = map; this.shim = getOwn(config.shim, map.id); this.depExports = []; this.depMaps = []; this.depMatched = []; this.pluginMaps = {}; this.depCount = 0; }; Module.prototype = { //初始化,根據(jù)options.enabled ? this.enable() : this.check() init: function (depMaps, factory, errback, options) {}, //通過this.depCount判斷依賴是否加載完成 defineDep: function (i, depExports) {}, // map.prefix ? this.callPlugin() : this.load(); fetch: function () {}, //通過context.load調(diào)req.load加載js文件 load: function () {}, //define模塊調(diào)用 check: function () {}, //加載依賴 callPlugin: function () {}, //data-main上的模塊調(diào)用,define模塊調(diào)用 enable: function () {}, //將cb推入this.events[name] on: function (name, cb) {}, //name === "error"刪this.events[name];否則循環(huán)this.events[name]執(zhí)行cb(evt); emit: function (name, evt) {} }; //module.init內(nèi)執(zhí)行check()非enable(); function callGetModule(args) {} //移除監(jiān)聽事件 function removeListener(node, func, name, ieName) {} //移除監(jiān)聽事件,返回節(jié)點(diǎn) function getScriptData(evt) {} // 獲取并加載defQueue中的模塊 function intakeDefines() {} context = { config: config, contextName: contextName, registry: registry, defined: defined, urlFetched: urlFetched, defQueue: defQueue, defQueueMap: {}, Module: Module, makeModuleMap: makeModuleMap, nextTick: req.nextTick, onError: onError, //配置參數(shù) 調(diào)用context.require(cfg.deps || [], cfg.callback); configure: function (cfg) {}, //返回閉包接口供調(diào)用 makeShimExports: function (value) {}, //返回閉包接口供調(diào)用 makeRequire: function (relMap, options) { //makeRequire的實(shí)際執(zhí)行函數(shù),生成宏任務(wù); function localRequire(deps, callback, errback) { return localRequire; } mixin(localRequire, { isBrowser: isBrowser, toUrl: function (moduleNamePlusExt) {}, defined: function (id) {}, specified: function (id) {} }); if (!relMap) { localRequire.undef = function (id) {}; } return localRequire; }, //調(diào)用 module的enable() enable: function (depMap) {}, //完成加載后 completeLoad: function (moduleName) {}, //根據(jù)moduleName獲取url nameToUrl: function (moduleName, ext, skipExt) {}, //調(diào)用req.load() load: function (id, url) {}, //return callback.apply(exports, args); execCb: function (name, callback, args, exports) {}, //加載完成后 onScriptLoad: function (evt) {}, //加載錯(cuò)誤 onScriptError: function (evt) {} }; context.require = context.makeRequire(); return context; } //入口函數(shù) req = requirejs = function (deps, callback, errback, optional) {}; //return req(config); req.config = function (config) {}; //宏任務(wù) req.nextTick = typeof setTimeout !== "undefined" ? function (fn) { setTimeout(fn, 4); } : function (fn) { fn(); }; //req賦值給require if (!require) { require = req; } req.version = version; req.jsExtRegExp = /^/|:|?|.js$/; req.isBrowser = isBrowser; s = req.s = { contexts: contexts, newContext: newContext }; //初始調(diào)用 req({}); each([ "toUrl", "undef", "defined", "specified" ], function (prop) { req[prop] = function () { var ctx = contexts[defContextName]; return ctx.require[prop].apply(ctx, arguments); }; }); if (isBrowser) { head = s.head = document.getElementsByTagName("head")[0]; baseElement = document.getElementsByTagName("base")[0]; if (baseElement) { head = s.head = baseElement.parentNode; } } req.onError = defaultOnError; //創(chuàng)建節(jié)點(diǎn) req.createNode = function (config, moduleName, url) {}; //節(jié)點(diǎn)綁定事件,添加到頭部,并返回節(jié)點(diǎn) req.load = function (context, moduleName, url) {}; //返回狀態(tài)為interactive的節(jié)點(diǎn) function getInteractiveScript() {} //data-main上的值解析賦給cfg if (isBrowser && !cfg.skipDataMain) { eachReverse(scripts(), function (script) { if (!head) { head = script.parentNode; } dataMain = script.getAttribute("data-main"); if (dataMain) { mainScript = dataMain; if (!cfg.baseUrl && mainScript.indexOf("!") === -1) { src = mainScript.split("/"); mainScript = src.pop(); subPath = src.length ? src.join("/") + "/" : "./"; cfg.baseUrl = subPath; } mainScript = mainScript.replace(jsSuffixRegExp, ""); if (req.jsExtRegExp.test(mainScript)) { mainScript = dataMain; } cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; return true; } }); } //定義模塊的函數(shù) define = function (name, deps, callback) {}; define.amd = { jQuery: true }; req.exec = function (text) {}; //將data-main的值解析代入req函數(shù); req(cfg); }(this, (typeof setTimeout === "undefined" ? undefined : setTimeout)));二、詳細(xì)流程
1、初始化變量;
2、執(zhí)行 req({})
req({})
context = contexts[contextName] = req.s.newContext(contextName);
說明:contextName="_",返回context這個(gè)東西,context.require = context.makeRequire();=localRequire;調(diào)用makeRequire實(shí)際調(diào)用makeRequire里的localRequire
context.configure(cfg);
說明:cfg=config={},什么都沒干
return context.require(deps, callback, errback);
說明:調(diào)用makeRequire里的localRequire;deps=[];
intakeDefines();
takeGlobalQueue();
說明:intakeDefines的子函數(shù),兩者什么都沒執(zhí)行
context.nextTick(function () { intakeDefines(); requireMod = getModule(makeModuleMap(null, relMap)); requireMod.skipMap = options.skipMap; requireMod.init(deps, callback, errback, { enabled: true }); checkLoaded(); });
說明:產(chǎn)生一個(gè) 宏任務(wù)1 函數(shù);req({})函數(shù)完
3、執(zhí)行 req(cfg)
獲取data-main上的值并解析成cfg
req(cfg);
說明:cfg={baseUrl:"data-main解析值1",deps:[data-main解析值2]}
context = getOwn(contexts, contextName);
說明:獲取之前產(chǎn)生的context;
context.configure(cfg);
說明:cfg=config={baseUrl:"data-main解析值1",deps:[data-main解析值2]}
config[prop] = value;
說明:屬性值給config
context.require(cfg.deps || [], cfg.callback);
說明:調(diào)用makeRequire里的localRequire;deps=[data-main解析值2];
intakeDefines(); takeGlobalQueue();
說明:什么都沒執(zhí)行
context.nextTick(function () {
說明:產(chǎn)生一個(gè) 宏任務(wù)2 函數(shù);
return context.require(deps, callback, errback);
說明:調(diào)用makeRequire里的localRequire;deps=[];
intakeDefines(); takeGlobalQueue();
說明:什么都沒執(zhí)行
context.nextTick(function () {
說明:產(chǎn)生一個(gè) 宏任務(wù)3 函數(shù);req(cfg);函數(shù)完
4、第一個(gè)宏任務(wù)開始
intakeDefines(); takeGlobalQueue();
說明:什么都沒執(zhí)行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
說明:返回一個(gè)對象obj
nameParts = splitPrefix(name);
說明:name="_@r2"
normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName);
parentModule = syms.slice(0, i).join("/");
說明:parentModule="_@r2"
getModule(obj)
new context.Module(depMap)
說明:depMap=上面返回的對象obj;getModule返回context.Module實(shí)例requireMod
requireMod.init(deps, callback, errback, {enabled: true}); this.enable(); enabledRegistry[this.map.id] = this; this.check(); cleanRegistry(id);
this.emit("defined", this.exports); checkLoaded();
說明:什么都沒執(zhí)行,第一個(gè)宏任務(wù)完。
5、第二個(gè)宏任務(wù)開始
intakeDefines(); takeGlobalQueue();
說明:什么都沒執(zhí)行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
說明:返回一個(gè)對象obj
nameParts = splitPrefix(name);
說明:name="_@r3"
normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName);
parentModule = syms.slice(0, i).join("/");
說明:parentModule="_@r3"
getModule(obj)
new context.Module(depMap)
說明:depMap=上面返回的對象obj;getModule返回context.Module實(shí)例requireMod
requireMod.init(deps, callback, errback, {enabled: true});
說明: deps 變?yōu)?data-main解析值2
this.enable(); enabledRegistry[this.map.id] = this; depMap = makeModuleMap(depMap,(this.map.isDefine ? this.map : this.map.parentMap), false,!this.skipMap); nameParts = splitPrefix(name); normalizedName = normalize(name, parentName, applyMap); url = context.nameToUrl(normalizedName); " on(depMap, "defined", bind(this, function (depExports) {this.defineDep(i, depExports);this.check();})); " mod = getModule(depMap); mod = registry[id] = new context.Module(depMap); mod.on(name, fn); getModule(depMap).enable(); this.check(); checkLoaded();
說明: 宏任務(wù)2結(jié)束
6、宏任務(wù)3同宏任務(wù)1
7、執(zhí)行data-main引入的文件的require函數(shù)
require(["./example"],function(example){example.test();}); req = requirejs = function (deps, callback, errback, optional) { return context.require(deps, callback, errback); intakeDefines(); takeGlobalQueue(); context.nextTick(function () {
說明: 產(chǎn)生一個(gè)宏任務(wù)4函數(shù);require函數(shù)結(jié)束
onScriptLoad: function (evt) { var data = getScriptData(evt); context.completeLoad(data.id); shim = getOwn(config.shim, moduleName) || {}, takeGlobalQueue(); callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
說明: require函數(shù)結(jié)束后執(zhí)行
8、宏任務(wù)4同宏任務(wù)2
說明: deps變?yōu)?要加載的依賴
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107357.html
摘要:以前一直對前端構(gòu)建工具的理解不深,經(jīng)過幾天的研究特意來總結(jié)一下,第一次寫博客,有寫錯(cuò)的請多多見諒,該文章我也從其他博客拷了一些內(nèi)容,如果有冒犯之處,請指出。強(qiáng)大的設(shè)計(jì)使得它更像是一個(gè)構(gòu)建平臺(tái),而不只是一個(gè)打包工具。 以前一直對前端構(gòu)建工具的理解不深,經(jīng)過幾天的研究特意來總結(jié)一下,第一次寫博客,有寫錯(cuò)的請多多見諒,該文章我也從其他博客拷了一些內(nèi)容,如果有冒犯之處,請指出。 如今,網(wǎng)頁不再...
摘要:概述是一款遵循規(guī)范協(xié)議的模塊加載器,不但能在瀏覽器端充分利用,同樣能在其他的運(yùn)行時(shí)環(huán)境,比如和。使用像這樣的模塊加載器能提高代碼的質(zhì)量和開發(fā)速度。一般放在頁面的入口出,用來加載其他的模塊。 RequireJS概述 RequireJS是一款遵循AMD規(guī)范協(xié)議的JavaScript模塊加載器, 不但能在瀏覽器端充分利用,同樣能在其他的JavaScript運(yùn)行時(shí)環(huán)境, 比如Rhino和No...
摘要:本文主要簡單地解讀一下的源碼和模塊化原理。其中,是這次源碼解讀的核心,但我也會(huì)順帶介紹一下其他文件的作用的。對代碼比較簡單,其實(shí)就是聲明一下全局的命名空間。然而,真正的核心在于處理模塊依賴的問題。 seajs 簡單介紹 seajs是前端應(yīng)用模塊化開發(fā)的一種很好的解決方案。對于多人協(xié)作開發(fā)的、復(fù)雜龐大的前端項(xiàng)目尤其有用。簡單的介紹不多說,大家可以到seajs的官網(wǎng)seajs.org參看...
摘要:一句化即它是插件的插件,作者事后才發(fā)現(xiàn)有這么一個(gè)插件繞了不少彎路。這里的主要是為了保存這段內(nèi)容用于打包使用。免費(fèi)領(lǐng)取驗(yàn)證碼內(nèi)容安全短信發(fā)送直播點(diǎn)播體驗(yàn)包及云服務(wù)器等套餐更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)分享請?jiān)L問網(wǎng)易云社區(qū)。文章來源網(wǎng)易云社區(qū) 本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。 前言我這里就不介紹requirejs了, 簡而言之: requirejs是支持AMD規(guī)范的模塊加載器, 事實(shí)上它也是...
摘要:我覺得那時(shí)他可能并沒有料到,這一規(guī)則的制定會(huì)讓整個(gè)前端發(fā)生翻天覆地的變化。前言 作為一名前端工程師,每天的清晨,你走進(jìn)公司的大門,回味著前臺(tái)妹子的笑容,摘下耳機(jī),泡上一杯茶,打開 Terminal 進(jìn)入對應(yīng)的項(xiàng)目目錄下,然后 npm run start / dev 或者 yarn start / dev 就開始了一天的工作。 當(dāng)你需要進(jìn)行時(shí)間的轉(zhuǎn)換只需要使用 dayjs 或者 momentj...
閱讀 1265·2021-09-27 13:35
閱讀 2563·2021-09-06 15:12
閱讀 3380·2019-08-30 15:55
閱讀 2829·2019-08-30 15:43
閱讀 432·2019-08-29 16:42
閱讀 3446·2019-08-29 15:39
閱讀 3062·2019-08-29 12:28
閱讀 1239·2019-08-29 11:11