s94-require
Version:
可以在浏览器中直接使用CommonJS的模块,书写语法和nodejs一样
212 lines (210 loc) • 7.99 kB
JavaScript
(function( window, factory) {
"use strict";
if (typeof require === "function" && typeof module === "object" && typeof module.exports === "object"){
module.exports = factory(window, true);
} else {
factory(window);
}
})(typeof window !== "undefined" ? window : this, function(window, isRequire){
"use strict";
if(isRequire) return require;
var _s94={};
_s94.__stack = function(index){
try{''.join();}catch(err){
var stack = err.stack.split('\n');
if(stack[0].indexOf('.join is not a function')!=-1) stack.shift();
var flc = /((?:https?|file)\:\/\/[^\040]+):(\d+):(\d+)/;
if(typeof index == 'undefined'){
for (var i = 0,res=[]; i < stack.length; i++) {
var m = stack[i].match(flc);
if(!m) continue;
res.push({'file': m[1], 'line': m[2], 'column': m[3]})
}
return res;
}else{
var m = stack[index].match(flc);
return m ? {'file': m[1], 'line': m[2], 'column': m[3]} : {};
}
}
};
_s94.dirname = function(path){
var mt = path.toString().match(/^([\s\S.]+)[\/\\][^\/\\]+[\/\\]?$/);
return mt ? mt[1] : '';
};
_s94.url = function(str, base){
var base = /^(http|file)/.test(base) ? base : window.location.href;
return new window['URL'](str, base);
}
_s94.encode = function(data){
var strmap = '0123456789abcdefghijklmnopqrstuvwxyz';
var cache = strmap;
var res='';
function encode(str){
var res='';
for (var i = 0; i < str.length; i++) {
res += str.charCodeAt(i).toString(36);
}
return res;
}
function char_code(char, i){
return strmap.indexOf(char[i])
}
var str = encode(data);
for (var i = 0,j=0; i < str.length; i++) {
j = i%36;
if(j==0) {
res = cache;cache = '';
}
var v = (char_code(str,i) + char_code(res, j)) % 36;
cache += strmap[v];
}
return cache + res.substring(cache.length);
}
_s94.cache = function(name, value, timeout){
if(typeof(value) == 'undefined'){
var cache_name = 's94_cache-'+_s94.encode(name);
try {
var data = JSON.parse(window.sessionStorage.getItem(cache_name));
if(!data) return undefined;
return data['main'];
} catch (error) {
return undefined;
}
}else{
var cache_name = 's94_cache-'+_s94.encode(name);
var data = JSON.stringify({main: value, name:name});
window.sessionStorage.setItem(cache_name, data);
}
}
_s94.cache.remove = function(name){
var cache_name = 's94_cache-'+_s94.encode(name);
window.sessionStorage.removeItem(cache_name);
}
_s94.getFile = function(setup){
setup.async = false;
var cacheData,cacheRes;
if(setup.cache && typeof(cacheData = _s94.cache(setup.url))!='undefined'){
try { //缓存获取的数据不可信,需要谨慎运行,防止报错后中断正常请求
cacheRes = typeof(setup.success)=="function" ? setup.success.call(setup, cacheData) : undefined;
setup.async = true; //执行缓存后,强制使用异步,避免阻断
} catch (error) {
_s94.cache.remove(setup.url);
cacheData = undefined;
}
}
function iseq(a, b){
if(a==b) return true;
try {
if(typeof(a)!='string') a = JSON.stringify(a);
if(typeof(b)!='string') b = JSON.stringify(b);
return a==b;
} catch (error) {
return false
}
}
var xhr = new XMLHttpRequest();
xhr.open('get', setup.url, setup.async);
var ac = function(xhr){
if(xhr && xhr.readyState == 4) {
if (xhr.status == 200) {
var resType = xhr.getResponseHeader('Content-Type');
var data = resType && resType.indexOf('/json')>0 ? JSON.parse(xhr.responseText) : xhr.responseText;
cacheData = _s94.cache(setup.url);
if(!iseq(cacheData, data)){
_s94.cache(setup.url, data);
if(typeof(cacheData)=='undefined') setup.success(data);
}
}else{
setup.error();
}
}
};
xhr.onreadystatechange = function(){ac(xhr)};
xhr.send();
}
function s94_require(engine){
function Module(id, parent, loaded){
this.id = id;
this.exports = {};
this.parent = (parent instanceof Module) ? parent : null;
this.filename = id;
this.loaded = !!loaded;
}
function _require(name, executeFile){
if(_require.cache[name] instanceof Module) return _require.cache[name].exports;
executeFile = typeof(executeFile)=='string' && /^(http|file)/.test(executeFile) ? executeFile : engine.__stack(2)['file'];
var _url, paths = [], path_index=0;
function _load(){
_url = paths[path_index]
if(!_url || _require.cache[_url] instanceof Module) return;
engine.getFile({
url: _url,
global: false,async: false,cache: true,refresh: false,
success: function(txt){
if(/package\.json$/.test(_url)){
if(!txt['main']) return path_index++,_load();
paths[path_index] = engine.url(txt['main'], _url).href;
_load();
}else{
var parent = _require.cache[executeFile] || _require.cache[window.location.href];
_require.cache[_url] = new Module(_url, parent);
if(/\.json/.test(_url)){//普通json文件
_require.cache[_url].exports = txt;
}else{
var str_url = _url.replace('"','\\"');
txt = `var _r=window.require;var require=function(n){return _r(n,"${str_url}")};require.cache=_r.cache;var module=require.cache["${str_url}"];var exports=module.exports;if(_r.debug)console.log(module.id);\n`+txt;
(new Function(txt)).call(window);
}
_require.cache[_url].loaded = true;
}
},
error: function(){path_index++;_load()}
});
}
//解析模板文件路径
var is_file = /\/.+\.(js|cjs|json)$/.test(name); //是否为文件地址
var is_path = /^(\/|\.\/|\.\.\/|http:)/.test(name); //是否为路径
var path = is_path ? engine.url(name, executeFile).href : _require.dir+'/'+name; //没有前导 '/'、'./'、'../' 则在模块目录查找
//[path]、[path].js、[path].json、[path]/package.json、[path]/index.js
paths.push(path+'.js'); //4
paths.push(path+'.json'); //5
//从模块目录加载或者以“/”结尾的优先按目录加载,否则优先按文件加载
if(!is_path || /\/$/.test(path)){
paths.unshift(path+'/index.js'); //3
paths.unshift(path+'/package.json'); //2
}else{
paths.push(path+'/package.json'); //6
paths.push(path+'/index.js'); //7
}
//模块名称疑似文件的最先按当前名称查找文件,否则最后按当前名称查找文件
if(is_file){
paths.unshift(path); //1
}else{
paths.push(path); //8
}
//加载
_load();
if(_require.cache[_url] instanceof Module){
if(name != _url) _require.cache[name] = _require.cache[_url];
return _require.cache[_url].exports;
}
throw new Error( 'require:模块'+name+'不存在');
}
_require.cache = {};
_require.dir = engine.dirname(engine.dirname(engine.filename));
if(!window.require || typeof(window.require.cache)=="undefined"){
_require.cache[window.location.href] = new Module(window.location.href, false, true);
Object.defineProperty(window, 'require', { value: _require });
try{window['global'] = window['GLOBAL'] = window;}catch(e){}
console.log('自定义require');
}
return Module;
}
_s94.filename = _s94.url(_s94.__stack(1)['file']).href;
//自定义require,同时创建root(window.location.href)模块
var Module = s94_require(_s94);
//注册当前模块
window.require.cache[_s94.filename] = new Module(_s94.filename, window.require.cache[window.location.href], true);
window.require.cache[_s94.filename].exports = window.require;
window.require.cache['s94-require'] = window.require.cache[_s94.filename];
})