前言
nodejs的require看上去和使用上去十分的优雅,所以兴趣之余,也想去尝试实现以下;
线上案例 : http://test1.ecoder.cc/loadSyn
源码:https://github.com/backsen/loadSyn
难登大雅,大神勿喷
准备开始
千里之行始于足下,一切都得从准备工作开始,那就是创建一个空文件夹:loadSyn
mkdir loadSyn
选择一款自己熟悉的编辑器
正式开始
在根目录下创建loader.js文件
(function(window){
var allModules = window.allModules = {},
loadScript = function(src , module){
var ajax = new XMLHttpRequest;
try{
ajax.onload = function(){
if(ajax.status == 200){
var importsArrs = ajax.responseText.match(/imports\((.*)\)/gm) || [];
var devs = [];
for(var i = 0 , len = importsArrs.length; i < len; i++){
devs.push(importsArrs[i].replace(/imports\((.*)\)/g , "$1"));
}
module['devs'] = devs;
var currentPath = module.src;
var scriptCode = ajax.responseText.replace(/imports\((.*)\)/gm , `imports($1 , currentPath)`);
var callBack = new Function("module" , "exports" , "imports" , "currentPath" ,`
imports.route = module.src;
${scriptCode};
module = module;
module.exports = !exports.isExports ? exports : module.exports;
return module;
`);
module = callBack(module , {isExports : true} , imports , currentPath);
delete callBack;
module.loaded = true;
}else if(ajax.status == 404 && src.indexOf("index.js") == -1){
src = src.substr(0 , src.lastIndexOf(".js")) + "/index.js";
module['src'] = src;
module.exports = loadScript(src, module);
}else{
module.exports = `${ajax.status} -- ${ajax.statusText}`;
}
}
ajax.onerror = function(){
return false;
}
ajax.open("GET" , src , false);
ajax.send(null);
return module.exports;
}catch(e){
console.error(e);
}
return module.exports;
},
src = "/",
getSrc = function(path , src , after){
var rootPath = location.origin + location.pathname.substr(0 , location.pathname.lastIndexOf("/")) + "/" ,
currentPath = path ? path.substr(0 , path.lastIndexOf("/")) + "/" : rootPath, url = currentPath;
if( /^\.\//.test(src)){
url = currentPath;
src = src.replace("./" , "");
}else if(/^(http|https):\/\//.test(src)){
url = "";
}else if(/^\.\.\//.test(src)){
url = currentPath;
}else{
url = rootPath;
var paths = loader.config.paths || {} ,
isModule = true;
for(var name in paths){
var srcPath = src.split("/");
if(srcPath[0] == name){
isModule = false;
if(srcPath[0] != paths[name]){
srcPath[0] = paths[name];
src = srcPath.join("/");
}
}
}
if(isModule && src != "loader.config.js") src = "modules/" + src;
}
url += src;
if(url[url.length - 1] == "/") url += "index.js";
if((!after || after == "js") && url.lastIndexOf(".js") == -1) url += "." + after || ".js";
return url;
},
imports = function(moduleUrl , currentPath){
var type = getFileType(moduleUrl) || "js";
var src = getSrc(currentPath || imports.route , moduleUrl , type);
if(allModules[src] && allModules[src]['loaded']){
return allModules[src].exports;
}
var module = allModules[src] = {
loaded : false,
name : moduleUrl,
src : src,
exports :{},
}
var myLoaders = loader.config.loaders;
if(myLoaders && myLoaders[type] && type != "js"){
return imports(myLoaders[type] + "/")(module.src, module);
}else{
return loadScript(module.src, module);
}
},
getFileType = function(url){
var type = "" , types = loader.config['fileTypes'] || ["js" , "json" , "css" , "html"];
for(var i = 0 , len = types.length; i <len; i++){
if(new RegExp("\." + types[i] + "$" , "gim").test(url)){
type = types[i];
}
}
return type;
},
bootloader = function(){
var config = imports("loader.config.js");
loader.loaders = {};
for(var name in config){
loader.config[name] = config[name];
}
loader.config['loaders'] = loader.config['loaders'] || {};
for(var name in loader.config.loaders){
loader.loaders[name] = imports(loader.config.loaders[name] + "/");
}
if(config['main']){
imports.route = "";
imports(config.main);
}
},
loader = {
config : {
loaders : {
"json" : "json-loader",
"js" : "js-loader"
},
fileTypes : ["js" , "json" , "css" , "html"]
},
loaders : {},
bootloader : bootloader
};
imports.route = "/";
loader.bootloader();
window.imports = imports;
})(window)
在根目录下创建index.html文件
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id = "main">
<app-root></app-root>
</div>
<script src="loader.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
在根目录下创建loader.config.js
exports = {
main : "./src/main.js",
paths : {
"datas" : "/datas",
"assets" : "/src/assets"
},
fileTypes : ["js" , "json" , "css" , "html" , "jpg" , "png" , "gif"],
loaders : {
"json" : "json-loader",
"js" : "js-loader",
"html" : "url-loader",
"css" : "url-loader" ,
"jpg" : "img-loader",
"png" : "img-loader",
"gif" : "img-loader"
}
}
在根目录下创建src目录,并且在src目录下创建一个main.js
console.log('holle wolrd')
现在的loadSyn目录下应该会像这样:
本章结束
这一章就这么多了,可以去看github上的源码,下一章会说说loaders