// 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
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));
}