JavaScript模块化:requirejs按需同步加载(一)

前言

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 

在根目录下创建index.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目录下应该会像这样:

JavaScript模块化:requirejs按需同步加载(一)_第1张图片
目录

本章结束

这一章就这么多了,可以去看github上的源码,下一章会说说loaders

你可能感兴趣的:(JavaScript模块化:requirejs按需同步加载(一))