摘要:說明內容主要包括三部分按源碼的結構順序對所有的變量及方法的說明運行流程流程相關圖片一源碼的結構為了方便比對源碼,按源碼的結構順序展示。
說明:
內容主要包括三部分:
1.按源碼的結構順序 對 所有的變量及方法的說明
2.requirejs運行流程
3、流程相關圖片
為了方便比對源碼,按源碼的結構順序展示。
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函數的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) {} //判斷函數 function isFunction(it) {} //判斷數組 function isArray(it) {} //執行函數func(ary[i], i, ary);返回真值,跳出循環 function each(ary, func) {} //與each序列反 function eachReverse(ary, func) {} //判斷obj是否有prop function hasProp(obj, prop) {} //返回obj上的prop function getOwn(obj, prop) {} //循環調用func(obj[prop], prop);返回真值,跳出循環 function eachProp(obj, func) {} //混合source屬性值(target沒有同名的)到target //force為真,target同名覆蓋,deepStringMixin為真,深混合 function mixin(target, source, force, deepStringMixin) {} //返回逆名函數,執行為obj調用fn函數 function bind(obj, fn) {} //返回script元素的集合 function scripts() {} //throw err; function defaultOnError(err) {} //例getGlobal("aa.bb");為global.aa.bb function getGlobal(value) {} //生成一個錯誤 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中.刪除此項;..刪此項和前一項除(i === 0 || (i === 1 && ary[2] === "..") || ary[i - 1]==="..") function trimDots(ary) {} //路徑處理.config.pkgs有name值優先,無值按相對路徑轉化,apply是否啟用地圖配置 function normalize(name, baseName, applyMap) {} //刪除data-requiremoduley為name和data-requirecontext === context.contextName的script function removeScript(name) {} //先移除再加載模塊; function hasPathFallback(id) {} //第一個"!"分離的前后數據 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 或 加載出錯且name為error ? 執行fn : 模塊綁定事件 function on(depMap, name, fn) {} //errback ? 執行errback(err) : mod.emit("error", err)執行刪除操作 function onError(err, errback) {} //將globalDefQueue推入defQueue function takeGlobalQueue() {} //commonjs風格 handlers = { //mod.require ? 返回mod.require : localRequire "require": function (mod) {}, "exports": function (mod) {}, "module": function (mod) {} }; //清除registry[id]、enabledRegistry[id] function cleanRegistry(id) {} //遞歸mod.depMaps,執行mod.check(); function breakCycle(mod, traced, processed) {} //檢查加載狀態,不同狀態執行不同操作 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 = { //初始化,根據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調req.load加載js文件 load: function () {}, //define模塊調用 check: function () {}, //加載依賴 callPlugin: function () {}, //data-main上的模塊調用,define模塊調用 enable: function () {}, //將cb推入this.events[name] on: function (name, cb) {}, //name === "error"刪this.events[name];否則循環this.events[name]執行cb(evt); emit: function (name, evt) {} }; //module.init內執行check()非enable(); function callGetModule(args) {} //移除監聽事件 function removeListener(node, func, name, ieName) {} //移除監聽事件,返回節點 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, //配置參數 調用context.require(cfg.deps || [], cfg.callback); configure: function (cfg) {}, //返回閉包接口供調用 makeShimExports: function (value) {}, //返回閉包接口供調用 makeRequire: function (relMap, options) { //makeRequire的實際執行函數,生成宏任務; 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; }, //調用 module的enable() enable: function (depMap) {}, //完成加載后 completeLoad: function (moduleName) {}, //根據moduleName獲取url nameToUrl: function (moduleName, ext, skipExt) {}, //調用req.load() load: function (id, url) {}, //return callback.apply(exports, args); execCb: function (name, callback, args, exports) {}, //加載完成后 onScriptLoad: function (evt) {}, //加載錯誤 onScriptError: function (evt) {} }; context.require = context.makeRequire(); return context; } //入口函數 req = requirejs = function (deps, callback, errback, optional) {}; //return req(config); req.config = function (config) {}; //宏任務 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 }; //初始調用 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; //創建節點 req.createNode = function (config, moduleName, url) {}; //節點綁定事件,添加到頭部,并返回節點 req.load = function (context, moduleName, url) {}; //返回狀態為interactive的節點 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; } }); } //定義模塊的函數 define = function (name, deps, callback) {}; define.amd = { jQuery: true }; req.exec = function (text) {}; //將data-main的值解析代入req函數; req(cfg); }(this, (typeof setTimeout === "undefined" ? undefined : setTimeout)));二、詳細流程
1、初始化變量;
2、執行 req({})
req({})
context = contexts[contextName] = req.s.newContext(contextName);
說明:contextName="_",返回context這個東西,context.require = context.makeRequire();=localRequire;調用makeRequire實際調用makeRequire里的localRequire
context.configure(cfg);
說明:cfg=config={},什么都沒干
return context.require(deps, callback, errback);
說明:調用makeRequire里的localRequire;deps=[];
intakeDefines();
takeGlobalQueue();
說明:intakeDefines的子函數,兩者什么都沒執行
context.nextTick(function () { intakeDefines(); requireMod = getModule(makeModuleMap(null, relMap)); requireMod.skipMap = options.skipMap; requireMod.init(deps, callback, errback, { enabled: true }); checkLoaded(); });
說明:產生一個 宏任務1 函數;req({})函數完
3、執行 req(cfg)
獲取data-main上的值并解析成cfg
req(cfg);
說明:cfg={baseUrl:"data-main解析值1",deps:[data-main解析值2]}
context = getOwn(contexts, contextName);
說明:獲取之前產生的context;
context.configure(cfg);
說明:cfg=config={baseUrl:"data-main解析值1",deps:[data-main解析值2]}
config[prop] = value;
說明:屬性值給config
context.require(cfg.deps || [], cfg.callback);
說明:調用makeRequire里的localRequire;deps=[data-main解析值2];
intakeDefines(); takeGlobalQueue();
說明:什么都沒執行
context.nextTick(function () {
說明:產生一個 宏任務2 函數;
return context.require(deps, callback, errback);
說明:調用makeRequire里的localRequire;deps=[];
intakeDefines(); takeGlobalQueue();
說明:什么都沒執行
context.nextTick(function () {
說明:產生一個 宏任務3 函數;req(cfg);函數完
4、第一個宏任務開始
intakeDefines(); takeGlobalQueue();
說明:什么都沒執行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
說明:返回一個對象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實例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();
說明:什么都沒執行,第一個宏任務完。
5、第二個宏任務開始
intakeDefines(); takeGlobalQueue();
說明:什么都沒執行
requireMod = getModule(makeModuleMap(null, relMap));
makeModuleMap(null, relMap)
說明:返回一個對象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實例requireMod
requireMod.init(deps, callback, errback, {enabled: true});
說明: deps 變為 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();
說明: 宏任務2結束
6、宏任務3同宏任務1
7、執行data-main引入的文件的require函數
require(["./example"],function(example){example.test();}); req = requirejs = function (deps, callback, errback, optional) { return context.require(deps, callback, errback); intakeDefines(); takeGlobalQueue(); context.nextTick(function () {
說明: 產生一個宏任務4函數;require函數結束
onScriptLoad: function (evt) { var data = getScriptData(evt); context.completeLoad(data.id); shim = getOwn(config.shim, moduleName) || {}, takeGlobalQueue(); callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
說明: require函數結束后執行
8、宏任務4同宏任務2
說明: deps變為 要加載的依賴
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107357.html
摘要:以前一直對前端構建工具的理解不深,經過幾天的研究特意來總結一下,第一次寫博客,有寫錯的請多多見諒,該文章我也從其他博客拷了一些內容,如果有冒犯之處,請指出。強大的設計使得它更像是一個構建平臺,而不只是一個打包工具。 以前一直對前端構建工具的理解不深,經過幾天的研究特意來總結一下,第一次寫博客,有寫錯的請多多見諒,該文章我也從其他博客拷了一些內容,如果有冒犯之處,請指出。 如今,網頁不再...
摘要:概述是一款遵循規范協議的模塊加載器,不但能在瀏覽器端充分利用,同樣能在其他的運行時環境,比如和。使用像這樣的模塊加載器能提高代碼的質量和開發速度。一般放在頁面的入口出,用來加載其他的模塊。 RequireJS概述 RequireJS是一款遵循AMD規范協議的JavaScript模塊加載器, 不但能在瀏覽器端充分利用,同樣能在其他的JavaScript運行時環境, 比如Rhino和No...
摘要:本文主要簡單地解讀一下的源碼和模塊化原理。其中,是這次源碼解讀的核心,但我也會順帶介紹一下其他文件的作用的。對代碼比較簡單,其實就是聲明一下全局的命名空間。然而,真正的核心在于處理模塊依賴的問題。 seajs 簡單介紹 seajs是前端應用模塊化開發的一種很好的解決方案。對于多人協作開發的、復雜龐大的前端項目尤其有用。簡單的介紹不多說,大家可以到seajs的官網seajs.org參看...
摘要:一句化即它是插件的插件,作者事后才發現有這么一個插件繞了不少彎路。這里的主要是為了保存這段內容用于打包使用。免費領取驗證碼內容安全短信發送直播點播體驗包及云服務器等套餐更多網易技術產品運營經驗分享請訪問網易云社區。文章來源網易云社區 本文由作者鄭海波授權網易云社區發布。 前言我這里就不介紹requirejs了, 簡而言之: requirejs是支持AMD規范的模塊加載器, 事實上它也是...
摘要:我覺得那時他可能并沒有料到,這一規則的制定會讓整個前端發生翻天覆地的變化。前言 作為一名前端工程師,每天的清晨,你走進公司的大門,回味著前臺妹子的笑容,摘下耳機,泡上一杯茶,打開 Terminal 進入對應的項目目錄下,然后 npm run start / dev 或者 yarn start / dev 就開始了一天的工作。 當你需要進行時間的轉換只需要使用 dayjs 或者 momentj...
閱讀 1273·2021-09-27 13:35
閱讀 2574·2021-09-06 15:12
閱讀 3390·2019-08-30 15:55
閱讀 2838·2019-08-30 15:43
閱讀 440·2019-08-29 16:42
閱讀 3452·2019-08-29 15:39
閱讀 3071·2019-08-29 12:28
閱讀 1249·2019-08-29 11:11