乐趣区

关于javascript:JS模块化-CMD

CMD usage

    // sea.js
    define('a', function(require, exports, module){console.log('a load');
        exports.run = function (){ console.log('a run') }
    })

    define('b', function(require, exports, module){console.log('b load');
        exports.run = function (){ console.log('b run') }
    })

    define('main', function(require, exports, module){console.log('main run');
        var a = require('a');
        a.run();
        var b = require('b');
        b.run();})

    seajs.use('main');

    // main run
    // a load
    // a run
    // b load
    // b run

seajs 简略实现

const modules = {};
const exports = {};

const sj = {}

// 获取地址
// dep -> a -> a.js -> http:xxx/xx/xx/a.js
const __getUrl = (dep) => {
    const p = location.pathname;
    return p.slice(0, p.lastIndexOf('/')) + '/' + dep + 'js';
}

// normal script
const __load = (url) => {return new Promise((resolve, reject) => {const header = document.getElementsByTagName("header")[0];
        const script = document.createElement('script');
        script.async = true;
        script.src = url;
        script.type = 'text/javascript';
        script.onload = resolve;
        script.onerror = reject;
        header.appendChild(script);
    }) 
}

const __getDepsFromFn = (fn) => {let matches = [];
    // require('a')
    // (?:require\() -> require((?:) 非捕捉性分组
    // (?:['"]) -> require(' 
    // ([^'"]+) -> a  防止回溯 -> 回溯 状态机
    let reg = /(?:require\()(?:['"])([^'"]+)/g
    let r = null;
    while((r = reg.exec(fn.toString())) !== null){
        reg.lastIndex;
        matches.push(r[1])
    }
    return matches;
}

// 依赖呢?// 提取依赖:1. 正则表达式 2. 状态机
const define = (id, factory) => {const url = __getUrl(id);
    const deps = __getDepsFromFn(factory);
    if(!modules[id]){modules[id] = {url, id, factory, deps};
    }
}

const __exports = (id) => exports[id] || (exports[id] = {});
const __module = this;
// 这里才是加载模块中央
// 这个写法是 promise 的  所以在 var a = require('a') 时 须要加 async/await 形式
const __require = (id) => {return __load(__getUrl(id)).then(() => {
        // 加载之后
        const {factory, deps} = modules[id];
        if(!deps || deps.length == 0){factory(__require, __exports(id), __module);
            return __exports(id);
        }
    })
}

sj.use = (mods, callback) => {mods = Array.isArray(mods) ? mods : [mods];
    return new Promise((resolve, reject) => {
        Promise.all(mods.map(mod =>{return __load(__getUrl(mod)).then(() => {
                // 加载之后
                const {factory} = modules[mod];
                factory(__require, __exports(mod), __module);
                return __exports(mod);
            })
        })).then(resolve, reject);
    }).then(instance => callback && callback(...instance));
}
退出移动版