äžåºŠãã³ã³ãã¥ãŒã¿ãŒã®åã«åº§ã£ãŠæ¬¡ã®äŸ¡å€ã®ãªããã³ãã£ãŒãèãããšãããã©ãŠã¶ãŒåŽãšãµãŒããŒåŽã§åãã³ãŒãã䜿çšããæ¹æ³ãå¿ èŠã§ããããšã«çªç¶æ°ä»ããŸããã ã»ãšãã©ããã«ãç§ã¯ããããããã»ã©é ãè¯ããªãã®ãæåã§ã¯ãªãããšã«æ°ä»ããŸããããããŠããã¹ãŠããã£ãšåã«ç§ã®ããã«çºæãããŠããŸããã
å®éãç§ã®èŠä»¶ã«ã€ããŠã¯ãããšãã°ã Node.jsã®ã¢ããã¿ãŒãåããRequireJS ãçŽ æŽãããã£ãã®ã§ããã°ããã®éãæ°ãŸããã«åºäŒãããšãã§ããŸãããäžã€ã®ãããžã§ã¯ãã§ïŒ ãã¹ãŠãçµ±äžããå¿ èŠããããŸãïŒã
ç¹°ãè¿ãã«ãªããŸãããCommonJSã¢ãžã¥ãŒã«ã«ã¯ãããããçš®é¡ã®ã¹ã¯ãªããã°ã«ãŒã¢ããµãŒããŒããªããã»ããµãåæããŒããŒãéåæã®ãã®ãªã©ãäœçŸäžãã®ãã©ãŠã¶å®è£ ããããŸããã ããããããããã¹ãŠã«1ã€ã®éåžžã«éèŠãªæ¬ ç¹ãããããšãå€æããŸããã äœããã®æ¹æ³ã§ã圌ãã¯ã¹ã¯ãªããã®ãœãŒã¹ã³ãŒããå€æŽãããã©ãŠã¶ã€ã³ã¹ãã¯ã¿ãŒã®ãããã°ããã»ã¹ãéåžžã«äžäŸ¿ã«ããŸããã
æã
ä»æ§ã«ããã°ãåã¢ãžã¥ãŒã«ã®ã°ããŒãã«åå空éã¯ãã¢ãžã¥ãŒã«èªäœã®å¢çå ã§ã®ã¿ã°ããŒãã«ã«ããå¿ èŠããããŸãã å¶éãè¶ ããŠã¯ãªããŸããã ãã®ãããªã¢ãžã¥ãŒã«ãå€æŽãããã«ãã©ãŠã¶ã«ããŒãããããšããã®ã³ãŒãã¯ã°ããŒãã«åå空éã§å®è¡ãããä»ã®ãã¹ãŠã®ã¢ãžã¥ãŒã«ãšå ±æãããŸãã ãããé¿ããããã«ãåã¢ãžã¥ãŒã«ã®ã³ãŒãã¯éåžžé¢æ°ã«ã©ããããããã®æ¹æ³ã§ã®ã¢ãžã¥ãŒã«åå空éã¯ããŒã«ã«ã«ãªããŸãã
ã¢ãžã¥ãŒã«ã¯ããã©ãŠã¶ã«ããŠã³ããŒãããåã«ãµãŒããŒäžã§ããŸãã¯ãã©ãŠã¶èªäœã§é¢æ°ã«ã©ããã§ããŸãã ã©ã¡ãã®å Žåããå®è¡å¯èœã³ãŒãã¯ãœãŒã¹ãšã¯ç°ãªãããããããã°ãå°é£ã«ãªããŸãã
ç§ãã¡ã¯ä»ã®æ¹æ³ã§è¡ããŸãã ãã®ã¡ãœããã®æ¬è³ªã¯ãåã¢ãžã¥ãŒã«ãåå¥ã®iframeã«ããŒãããããã«ãã£ãŠä»ã®ã¢ãžã¥ãŒã«ããåé¢ããããšã§ãã ãã®ãããªåãã¬ãŒã ã®åå空éã§ã¯ãCommonJSä»æ§ã®èŠä»¶ã«åŸã£ãŠãrequireé¢æ°ãšexportsããã³module.exportsãªããžã§ã¯ããäºåå®çŸ©ãããŸãã
æ®å¿µãªãããã¹ã¯ãªãããããŒããããã®æ¹æ³ã«ã¯æ¬ ç¹ããªãããã§ã¯ãããŸããã æåã«åºäŒã£ãã®ã¯ã芪ãŠã£ã³ããŠã®DOMããã®ä»ã®ã°ããŒãã«ãªããžã§ã¯ããæäœããããšã®äžäŸ¿ãã§ããã ãããã«ã¢ã¯ã»ã¹ããã«ã¯ãé¢åãªwindow.parent.windowã³ã³ã¹ãã©ã¯ãã䜿çšããå¿ èŠããããŸããããã«ãå°æ¥çã«çç£çšã«ã¢ãžã¥ãŒã«ãæ¥çãããå Žåã¯åé·ã«ãªããŸãã ãã®åé¡ã®è§£æ±ºçã¯ãäœããã®æ¹æ³ã§ãåiframeã«ã°ããŒãã«ãªããžã§ã¯ããäœæããããšã§ããããã¯ã芪ãŠã£ã³ããŠã®ãŠã£ã³ããŠãžã®ãªã³ã¯ã«ãªããŸãã ãã®ãªããžã§ã¯ããä»ããŠããŠã£ã³ããŠèªäœãããã¥ã¡ã³ããããã²ãŒã¿ãŒãå±¥æŽãªã©ã®ã¢ãžã¥ãŒã«ããã¢ã¯ã»ã¹ã§ããå¿ èŠã«å¿ããŠã°ããŒãã«å€æ°ã䜿çšã§ããŸãã
2ã€ç®ã¯ãäžèŠãããšããã»ã©æçœã§ã¯ãããŸããããã°ããŒãã«ã³ã³ã¹ãã©ã¯ã¿ãŒé¢æ°ïŒã¯ã©ã¹ïŒã®FunctionãDateãStringãªã©ãåäžã§ãªãããšã§ãã ããŸããŸãªã¢ãžã¥ãŒã«ã®ã³ã³ããã¹ãã§ã ããã«ãããããšãã°ããªããžã§ã¯ããå¥ã®ã¢ãžã¥ãŒã«ã§äœæãããå Žåããã®ãªããžã§ã¯ããçµã¿èŸŒã¿ã¯ã©ã¹ã«å±ããŠãããã©ããã確èªã§ããŸããã
var doSomething = require("./someModule").doSomething; // doSomething - , someModule console.log(doSomething instanceof Function); // false, Function Function someModule ( someFunction) -
ãã®åé¡ãééçã«è§£æ±ºããããšã¯äžå¯èœã§ãããããã³ãŒãã§åè¿°ãããã®ãšåæ§ã®æ§é ã䜿çšããªãããšã«åæããå¿ èŠããããŸãã ãŸãã¯ãæ éã«äœ¿çšããŠãã ããã å ·äœçã«ã¯ããã®äŸã§ã¯ãé¢æ°ãFunctionã¯ã©ã¹ã«å±ããŠãããã©ããã®ãã§ãã¯ããããšãã°æ¬¡ã®ããã«çœ®ãæããããšãã§ããŸãã
console.log(typeof doSomething === "function"); // true
CommonJSã¢ãžã¥ãŒã«ããã©ãŠã¶ãŒã«ããŒãããã人ã«ãšã£ãŠç掻ãå°é£ã«ãããã1ã€ã®ãã¥ã¢ã³ã¹ã¯ãCommonJSã®requireé¢æ°ã®åæçãªæ§è³ªã§ãã ãã®åé¡ã解決ããæãäžè¬çãªæ¹æ³ã¯ãç®çã®ã¢ãžã¥ãŒã«ãåæAJAXãªã¯ãšã¹ãã§ããŒãããããŠã³ããŒãããã³ãŒããè©äŸ¡ããããæ°ããFunctionïŒïŒã䜿çšããŠå¿åé¢æ°ãäœæããããšã§ãã ãã®å Žåããããã¬ãŒã¯å ã®ãã¡ã€ã«ã®ã³ãŒãè¡ãæãã®ãåæ¢ããããããã®æ¹æ³ã¯é©ããŠããŸããã ããäžåºŠãä»ã®æ¹æ³ã䜿çšããŸããããã«ãããæä»ããã®å®¹èµŠãªãè©äŸ¡ã³ãŒããéããŠåé¡ãªããããã¬ãŒãå®è¡ã§ããŸãã
requireé¢æ°ã¯ãåºæ¬çã«ã¯ãããŒããããã¢ãžã¥ãŒã«ã«ãã£ãŠãšã¯ã¹ããŒãããããã£ãã·ã¥ãããmodule.exportsãªããžã§ã¯ããè¿ãã ãã§ãã ã¢ãžã¥ãŒã«èªäœã®ã³ãŒãã¯ãã¢ãžã¥ãŒã«ãæåã«ããŒãããããšãããšãã«ã®ã¿å®è¡ãããŸãã
äžèšã念é ã«çœ®ããŠãã¡ãã£ãšããããªãã¯ãèŠãŠã¿ãŸãããããããã®ã¢ãžã¥ãŒã«ã䜿çšããã³ãŒããå®è¡ãããåã«ãäºåã«ã¢ãžã¥ãŒã«ãããŒãããŸãã ãã®å Žåããã¹ãŠã®ã¢ãžã¥ãŒã«ã®ãšã¯ã¹ããŒããã©ããã«ãã£ãã·ã¥ãããããã絶察åæé¢æ°requireãããããè¿ããŸãã
ãã¡ããããã®æ¹æ³ã«ãæ¬ ç¹ããªãããã§ã¯ãããŸããã ãã¹ãŠã®ã¢ãžã¥ãŒã«ãããªããŒãããã«ã¯ããããã®èå¥åïŒååïŒãæ£ç¢ºã«ç¥ãå¿ èŠããããŸãã ãããŠããã¯ããã®ã¡ãœããã䜿çšãããšãå®è¡æã«èå¥åãèšç®ãããã¢ãžã¥ãŒã«ãããªããŒãã§ããªãããšãæå³ããŸãã ã€ãŸãããããè¡ãããšã¯ã§ããŸããã
var a = someRandomValue(); require("./module" + a);
ããã«ããããããããã®åé¡ã解決ããããã«ãã¢ãžã¥ãŒã«ã®éåžžã®AJAXããŒãã£ã³ã°ã䜿çšãããã®ãããªå Žåã«evalã䜿çšããŠãçµæããã¹ãŠåŸãããšãã§ããŸãã
ã¢ãžã¥ãŒã«å ã®ã³ãŒãå®è¡ã®é åºããããšãã°Node.jsã®æ¡ä»¶ãªã©ãšç°ãªããšããåé¡ããŸã ãããŸãã 2ã€ã®å°ããªã¢ãžã¥ãŒã«ãæ€èšããŠãã ããã
// "a" exports.result = doSomeExternalOperation();
// "b" prepareDataForSomeExternalOperation(); var a = require("./a");
Node.jsã§ã¯ãæããã«ãprepareDataForSomeExternalOperationé¢æ°ã®åŒã³åºãã¯ãdoSomeExternalOperationåŒã³åºããããæ©ãçºçããŸãïŒãã ãããã®åã«ä»ã®requireïŒ "./ a"ïŒåŒã³åºãããªãã£ãå Žåã®ã¿ïŒã ç§ãã¡ã®å Žåãã¢ãžã¥ãŒã«aã¯ã¢ãžã¥ãŒã«bã®åã«ããŒãããã³å®è¡ãããããããã¹ãŠãéã«ãªããŸãã æ®å¿µãªããããã®æ¬ ç¹ã«ãææ ¢ããå¿ èŠããããŸãã ããããå ¬å¹³ã«èšããšãã¢ãžã¥ãŒã«ã®æ£ããèšèšã§ã¯ããã®ãããªç¶æ³ã¯çºçããªãã¯ãã§ãã ã¢ãžã¥ãŒã«ã®ã¡ã€ã³ã³ãŒãïŒãã¡ã€ã«ã·ã¹ãã ãããŒã¿ããŒã¹ãªã©ïŒã§ãä»ã®ã¢ãžã¥ãŒã«ã®åäœã«æé»çã«åœ±é¿ãåãŒãå¯èœæ§ã®ããå€éšã¢ã¯ã·ã§ã³ãå®è¡ããããšã¯é©åã§ã¯ãããŸããã
ããã§ãäžè¬çã«ããããŠãã©ãŠã¶ã«ã¢ãžã¥ãŒã«ãããŒãããããšã«ã€ããŠç§ãäŒãããã£ãããšãã¹ãŠã 説æããæ¹æ³ã誰ãã«ãšã£ãŠæçšã§ãããšæããã圌ã圌ã®ä»äºã§ããã䜿çšããããšã«æ±ºããå ŽåïŒè¯ããããã§ã¯ãã¹ãŠãåºæ¬çã§ãããå®è£ ã«åé¡ã¯ãªãã¯ãã§ãïŒãç§ã¯éåžžã«å¹žãã§ãã
ããããããªããçªç¶ä»äœãããããšããªãå ŽåããŸãã¯åã«èå³ãããå Žå-ç§ã®å®è£ ã®è©³çŽ°ã®èª¬æãžããããïŒ
ã³ãã£ã
ãœãŒã¹ã¯Githubã§ç¡æã§å ¥æã§ããŸãã
ãã®ãŠãŒãã£ãªãã£ãã¯ã©ã¹ã®åœ¢åŒã§èšèšããããšã«ããŸãããåã€ã³ã¹ã¿ã³ã¹ã¯ç¬èªã®æ§æãæã€åå¥ã®ã¢ããªã±ãŒã·ã§ã³ã«ãªããŸãïŒãã ããçŸæç¹ã§ã¯ãæ§æå šäœã¯1è¡ïŒãã¹ãŠã®ã¹ã¯ãªãããé 眮ãããŠãããã¹ïŒãšã¢ãžã¥ãŒã«ãã£ãã·ã¥ã§æ§æãããŸãïŒã
function Comeon(path) { var self = this; self.path = path; self.modules = {}; }
ã¯ã©ã¹ã«ã¯ãåäžã®ãããªãã¯éåæé¢æ°ãrequireãããããã¹ãŠã®äŸåé¢ä¿ã§ã¢ãžã¥ãŒã«ã®å®è¡ãéå§ãããªãã·ã§ã³ã§ã¡ã€ã³ã¢ãžã¥ãŒã«ãçµäºããŠãšã¯ã¹ããŒããã©ã¡ãŒã¿ãŒãåãåã£ãåŸã«åŒã³åºãããã³ãŒã«ããã¯é¢æ°ãåãå ¥ããŸãã
Comeon.prototype.require = function require(moduleRequest, callback) { var self = this; loadNextModule.bind(self)(enqueueModule.bind(self)(getModuleId("", moduleRequest)), callback); }
2ã€ã®äž»èŠã§æãèå³æ·±ãé¢æ°enqueueModuleãšloadNextModuleãæ€èšããåã«ãããã€ãã®ãã«ããŒæ©èœãæ€èšããŸãã
searchRequiresé¢æ°ã¯ããã©ã¡ãŒã¿ãŒãšããŠã¢ãžã¥ãŒã«ãã¡ã€ã«ã®URLãååŸããåæXHRèŠæ±ã§ãããããŒããããã®äžã®requireé¢æ°ãžã®åŒã³åºãã®çºçãæ¢ããŸãã ããŠã³ããŒãããã³ãŒããå®è¡ããã®ã§ã¯ãªãããã®é¢æ°ã䜿çšããŠã¢ãžã¥ãŒã«ã®äŸåé¢ä¿ãæ¢ããŠããã ãã§ãããšããäºå®ã«æ³šæãåèµ·ããããšæããŸãã ã¢ãžã¥ãŒã«ãã¡ã€ã«ã¯ããã®ããŠã³ããŒãäžã«ãã©ãŠã¶ã«ãã£ãŠãã£ãã·ã¥ãããŸããããã¯ãåŸã§ãã®ã¢ãžã¥ãŒã«ãæ¥ç¶ãããšãã«åœ¹ç«ã¡ãŸãã
var requirePattern = /(?:^|\s|=|;)require\(("|')([\w-\/\.]*)\1\)/g; function searchRequires(url) { var requires = []; var xhr = new XMLHttpRequest(); xhr.open("GET", url, false); xhr.onreadystatechange = function () { if ((xhr.readyState === 4) && (xhr.status === 200)) { var match; while ((match = requirePattern.exec(xhr.responseText)) !== null) { requires.push(match[2]); } } }; xhr.send(); return requires; }
getModuleIdããã³getModuleContexté¢æ°ã¯ãããããã¢ãžã¥ãŒã«ãžã®èå¥åãšãã¹ãååŸããããã«äœ¿çšãããŸãã
function getModuleId(moduleContext, moduleRequest) { var moduleId = []; (/^\.\.?\//.test(moduleRequest) ? (moduleContext + moduleRequest) : moduleRequest).replace(/\.(?:js|node)$/, "").split("/").forEach(function (value) { if (value === ".") { } else if (value === "..") { moduleId.pop(); } else if (/[\w\-\.]+/.test(value)) { moduleId.push(value); } }); return moduleId.join("/"); }
function getModuleContext(moduleId) { return moduleId.slice(0, moduleId.lastIndexOf("/") + 1); }
requireé¢æ°ã¯ãã¢ãžã¥ãŒã«ã®ã³ã³ããã¹ãã§ãèŠæ±ããããã£ãã·ã¥ããããšã¯ã¹ããŒããè¿ãé¢æ°ã§ãã 以åã«ã¢ããªã±ãŒã·ã§ã³ã€ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã«åºå®ããçŸåšã®ã¢ãžã¥ãŒã«ã®ãã¹ãæåã®ãã©ã¡ãŒã¿ãŒãšããŠæž¡ããŠãããåiframeããŠã£ã³ããŠã«é 眮ããŸãã
function require(moduleContext, moduleRequest) { var self = this; var moduleId = getModuleId(moduleContext, moduleRequest); if (self.modules[moduleId] && self.modules[moduleId].exports) { return self.modules[moduleId].exports; } else { throw Error("Module not found."); } }
æåŸã«ããã¹ãŠã®äž»èŠãªäœæ¥ãå®è¡ãã2ã€ã®æ©èœãæ€èšããŸãã
ååž°é¢æ°enqueueModuleã¯ããã©ã¡ãŒã¿ãŒãšããŠæž¡ãããã¢ãžã¥ãŒã«ããã¥ãŒã«è¿œå ããŸãããŸããäŸåé¢ä¿ããšã«èªåèªèº«ãåŒã³åºããŠè¿œå ããŸãã ãã®çµæãã¢ãžã¥ãŒã«ããŒããã¥ãŒãååŸããŸãããã¥ãŒã®æåŸã«ã¯ãã¡ã€ã³ã¢ãžã¥ãŒã«ïŒã¢ããªã±ãŒã·ã§ã³ãžã®ãšã³ããªãã€ã³ãïŒããããŸãã ãã®ãã¥ãŒã®ãããã§ãããŠã³ããŒãå¯èœãªåã¢ãžã¥ãŒã«ã¯ãäŸåãããã¹ãŠã®ãã£ãã·ã¥ãããã¢ãžã¥ãŒã«ããã§ã«èªç±ã«äœ¿çšã§ããŸãã
function enqueueModule(moduleId) { var self = this; var moduleQueue = []; if (!self.modules[moduleId]) { self.modules[moduleId] = { url: self.path + moduleId + ".js?ts=" + (new Date()).valueOf() }; moduleQueue.push(moduleId); searchRequires(self.modules[moduleId].url).forEach(function (value) { Array.prototype.push.apply(moduleQueue, enqueueModule.bind(self)(getModuleId(getModuleContext(moduleId), value))); }); } return moduleQueue; }
loadNextModuleé¢æ°ã¯ãenqueueModuleé¢æ°ã«ãã£ãŠè¿ããããã¥ãŒãééããã¢ãžã¥ãŒã«ãé ã«ãã©ãŠã¶ãŒã«ããŒãããŸãïŒäŸåé¢ä¿ãæ€çŽ¢ããããã«æ¢ã«ããŠã³ããŒãããããããã©ãŠã¶ãŒã¯ãã£ãã·ã¥ãããã¡ã€ã«ãååŸããŸãïŒã äžèšã§åæããããã«ãåã¢ãžã¥ãŒã«ãæ¥ç¶ããããã«ãã°ããŒãã«å€æ°ãexportsããã³module.exportså€æ°ãããã³requireé¢æ°ãäœæããåå¥ã®iframeã䜿çšãããŸãã 次ã®åiframeã¯ãåã®ã¹ã¯ãªãããå®å šã«ããŒããããåŸã«ã®ã¿ããŒããããŸãã ããŠã³ããŒããã¥ãŒãçµäºãããšãæåã«æž¡ãããã³ãŒã«ããã¯é¢æ°ïŒããå ŽåïŒãåŒã³åºããæåŸã®ã¢ãžã¥ãŒã«ã®ãšã¯ã¹ããŒããããã«è»¢éããŸãã
function loadNextModule(moduleQueue, callback) { var self = this; if (moduleQueue.length) { var iframe = document.createElement("iframe"); iframe.src = "about:blank"; iframe.style.display = "none"; iframe.onload = function () { var moduleId = moduleQueue.pop(); var iframeWindow = this.contentWindow; var iframeDocument = this.contentDocument; iframeWindow.global = window; iframeWindow.require = require.bind(self, getModuleContext(moduleId)); iframeWindow.module = { exports: {} } iframeWindow.exports = iframeWindow.module.exports; var script = iframeDocument.createElement("script"); script.src = self.modules[moduleId].url; script.onload = function () { self.modules[moduleId].exports = iframeWindow.module.exports; if (moduleQueue.length) { loadNextModule.bind(self)(moduleQueue, callback); } else if (typeof callback === "function") { callback(self.modules[moduleId].exports); } }; iframeDocument.head.appendChild(script); }; document.body.appendChild(iframe); } else if (typeof callback === "function") { callback(); } }
ããŸããšããŠãcomeon.jsã¹ã¯ãªãããèªã¿èŸŒãã çŽåŸã«ã¢ããªã±ãŒã·ã§ã³ãèµ·åã§ããæ©èœãè¿œå ããŸãã
var script = Array.prototype.slice.call(document.getElementsByTagName("script"), -1)[0]; var main = script.getAttribute("data-main"); if (main) { window.addEventListener("load", function () { var comeon = new Comeon(script.getAttribute("data-path") || "/"); comeon.require(main); }); }
以äžã§ãã ããã§ããã©ãŠã¶åŽã§CommonJS圢åŒã§èšè¿°ãããã¢ãžã¥ãŒã«ã䜿çšããåãã§ããã¥ãŒããããšãã§ããŸãã ãããè¡ãã«ã¯ãcomene.jsãã¹ã¯ãªãããžã®ãã¹ãšããŒã¿å±æ§ã®ã¡ã€ã³ã¢ãžã¥ãŒã«ã®ååã«æ¥ç¶ããã ãã§ãã
<script src="http://rawgithub.com/avgaltsev/comeon/master/comeon.js" data-path="scripts/" data-main="main"></script>
ãŸãã¯ãå®è¡ããã»ã¹äžã«äºãã«ç¬ç«ããè€æ°ã®ã¢ãžã¥ãŒã«ãæ¥ç¶ããå¿ èŠãããå ŽåããŸãã¯ã¢ããªã±ãŒã·ã§ã³ã«è€æ°ã®ãšã³ããªãã€ã³ããããå Žåããã詳现ãªæ§æã䜿çšã§ããŸãã
<script src="http://rawgithub.com/avgaltsev/comeon/master/comeon.js"></script> <script> window.onload = function () { var comeon = new Comeon("scripts/"); // comeon.require("main"); // comeon.require("another_main", function (exports) { console.log(exports); }); }; </script>