UNPKG

static-assets-loader

Version:
492 lines (395 loc) 12.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var loadjs = _interopDefault(require('loadjs')); /** * 检测错误并抛出 * @param condition 是否抛出错误 * @param errorMsg */ var invariant = function invariant(condition, errorMsg) { if (condition) { throw new Error(errorMsg); } }; /** * Get the website information of CDN * '//cdn.bootcdn.net/ajax/libs/vue/3.2.33/vue.runtime.esm-browser.js' => 'cdn.bootcdn.net' * @param url * @returns */ var getPrefixUrl = function getPrefixUrl(url) { if (!url) { return ''; } // https:// => 8 // http:// => 7 // // => 2 var removePrefixIndex = url.indexOf('//') + 2; // get all strings between the current index and the first following / as path return url.substring(removePrefixIndex, url.indexOf('/', removePrefixIndex)); }; /** * Gets the object on the global variable * vue => window.Vue * @param umdName * @returns */ var getWrapperDataFromGlobal = function getWrapperDataFromGlobal(umdName) { if (!umdName || typeof umdName !== 'string') { return null; } return globalThis[umdName]; }; /** * 获取一个resolve 和reject在外面的promise对象 * @returns {Promise<unknown>} */ var createDeferredPromise = function createDeferredPromise() { var resolve; var reject; var promise = new Promise(function (res, rej) { resolve = res; reject = rej; }); return { currentPromise: promise, resolve: resolve, reject: reject }; }; var getStorage = function getStorage(strategy) { if (strategy === 'sessionStorage') { return sessionStorage; } if (strategy === 'localStorage') { return localStorage; } return null; }; /** * Can't use URL */ var DEFAULT_MAX_AGE = 8 * (60 * 60); var STORAGE_KEY = 'balUrlPrefix'; var DEFAULT_OPTIONS = { storageKey: STORAGE_KEY, strategy: 'memory', maxAge: DEFAULT_MAX_AGE }; var BadUrlPrefixCache = /*#__PURE__*/function () { function BadUrlPrefixCache(config) { var _this = this; /** * Cache problematic URLs */ this.urlPrefixCache = new Map(); this.getCacheFromStorage = function () { var _getStorage; var json = (_getStorage = getStorage(_this.config.strategy || '')) == null ? void 0 : _getStorage.getItem(_this.config.storageKey || STORAGE_KEY); if (!json) { return {}; } try { return JSON.parse(json); } catch (error) { return {}; } }; this.add = function (url) { var prefixUrl = getPrefixUrl(url); if (_this.has(prefixUrl)) { return; } var expiredTime = new Date().getTime() / 1000 + DEFAULT_MAX_AGE; _this.urlPrefixCache.set(prefixUrl, expiredTime); _this.setStorageForCache(); return _this; }; this["delete"] = function (url) { if (_this.isEmpty()) { return; } _this.urlPrefixCache["delete"](getPrefixUrl(url)); _this.setStorageForCache(); return _this; }; this.isOverTime = function (prefixUrl) { var expiredTime = _this.urlPrefixCache.get(prefixUrl) || 0; // 没有数据项 一定超时 if (!expiredTime) { return true; } // 获取系统当前时间戳 var currentTime = new Date().getTime() / 1000; // 如果过去的秒数大于当前的超时时间,也返回null让其去服务端取数据 if (currentTime > expiredTime) { // 此代码可以没有,不会出现问题,但是如果有此代码,再次进入该方法就可以减少判断。 _this.urlPrefixCache["delete"](prefixUrl); return true; } // 不超时 return false; }; this.has = function (url) { var prefixUrl = getPrefixUrl(url); return !_this.isOverTime(prefixUrl); }; this.isEmpty = function () { return _this.urlPrefixCache.size === 0; }; this.getCanUseUrl = function (loadUrls) { var allUrls = loadUrls || []; if (_this.isEmpty()) { return allUrls[0] || ''; } return allUrls.find(function (url) { return !_this.has(url); }) || ''; }; this.config = Object.assign({}, DEFAULT_OPTIONS, config); if (this.config.strategy !== 'memory') { return; } var urlPrefixCacheObj = this.getCacheFromStorage(); Object.keys(urlPrefixCacheObj).map(function (url) { _this.urlPrefixCache.set(url, urlPrefixCacheObj[url]); }); } BadUrlPrefixCache.getInstance = function getInstance(config) { if (!BadUrlPrefixCache.badUrlPrefixCache) { BadUrlPrefixCache.badUrlPrefixCache = new BadUrlPrefixCache(config); } return BadUrlPrefixCache.badUrlPrefixCache; }; var _proto = BadUrlPrefixCache.prototype; _proto.setStorageForCache = function setStorageForCache() { var _getStorage2; var storageObj = {}; this.urlPrefixCache.forEach(function (value, key) { storageObj[key] = value; }); (_getStorage2 = getStorage(this.config.storageKey || '')) == null ? void 0 : _getStorage2.setItem(this.config.storageKey || STORAGE_KEY, JSON.stringify(storageObj)); }; return BadUrlPrefixCache; }(); BadUrlPrefixCache.badUrlPrefixCache = null; BadUrlPrefixCache.resetInstance = function (config) { BadUrlPrefixCache.badUrlPrefixCache = null; BadUrlPrefixCache.getInstance(config); }; var setBadUrlPrefixCacheOptions = function setBadUrlPrefixCacheOptions(options) { BadUrlPrefixCache.resetInstance(options); }; var badUrlPrefixCache = /*#__PURE__*/BadUrlPrefixCache.getInstance({ strategy: 'localStorage' }); var resloveCanUseUrl = function resloveCanUseUrl(moduleAssets) { var allUrls = (moduleAssets || {}).loadUrls || []; return badUrlPrefixCache.getCanUseUrl(allUrls); }; var isModuleAssets = function isModuleAssets(item) { return 'name' in item && 'loadUrls' in item; }; /** * * @param needLoadItems * @returns */ var moduleRetryLoad = function moduleRetryLoad(needLoadItems) { return new Promise(function (resolve, reject) { var startLoad = function startLoad(urls) { return loadjs(urls, { returnPromise: true }).then(function () { // Remove bad urls after success urls.forEach(function (url) { return badUrlPrefixCache["delete"](url); }); resolve('success'); })["catch"](function (failUrls) { // add bad urls after failure urls.forEach(function (url) { return badUrlPrefixCache.add(url); }); var retryUrls = []; var _loop = function _loop(i, len) { var failUrl = failUrls[i]; // find module that fail to load and check for alternative urls var failItem = needLoadItems.find(function (item) { return item.url === failUrl; }); if (!failItem || !failItem.moduleAssets) { return { v: void 0 }; } var newUrl = resloveCanUseUrl(failItem.moduleAssets); // there is no url that can be replaced, and an error is reported directly if (!newUrl) { failItem.moduleAssets.status = 'fail'; reject(new Error("Cannot load assets " + failItem.moduleAssets.name + " " + newUrl)); return { v: void 0 }; } retryUrls.push(newUrl); }; for (var i = 0, len = failUrls.length; i < len; i++) { var _ret = _loop(i); if (typeof _ret === "object") return _ret.v; } // retry until successful or all urls fail startLoad(retryUrls); }); }; var urlsToLoad = needLoadItems.map(function (x) { return x.url; }); startLoad(urlsToLoad); }); }; var cacheJsModules = {}; var deferred = /*#__PURE__*/createDeferredPromise(); var addJsModule = function addJsModule(module) { !!module ? invariant(false, 'module cannot empty') : void 0; var name = module.name, loadUrls = module.loadUrls; !!name ? invariant(false, 'module name cannot empty') : void 0; !(!Array.isArray(loadUrls) || !loadUrls.length) ? invariant(false, 'module loadUrls cannot empty') : void 0; if (cacheJsModules[name]) { return false; } module.status = 'ready'; cacheJsModules[name] = module; return true; }; var startLoad = function startLoad(jsAssets, isAssetsList, time) { if (time === void 0) { time = 1; } var loadItems = jsAssets.map(function (name) { var assets = cacheJsModules[name]; var item = { moduleAssets: assets, result: getWrapperDataFromGlobal(name) }; if (!item.result) { item.url = resloveCanUseUrl(assets); } return item; }); var currentNeedLoadItems = loadItems.filter(function (item) { return !item.result; }); if (!currentNeedLoadItems.length) { deferred.resolve(isAssetsList ? loadItems.map(function (item) { return item.result; }) : loadItems[0].result); return; } var errIndex = currentNeedLoadItems.findIndex(function (item) { return item.moduleAssets.status === 'fail'; }); if (errIndex > -1) { deferred.reject("Cannot load assets " + currentNeedLoadItems[errIndex].moduleAssets.name); return; } var loadingItems = currentNeedLoadItems.filter(function (item) { return item.moduleAssets.status === 'loading'; }); if (loadingItems.length === currentNeedLoadItems.length) { if (time > 10) { deferred.reject("load assets overtime"); return; } setTimeout(function () { startLoad(jsAssets, isAssetsList, time + 1); }, time * 100); } var needLoadItems = currentNeedLoadItems.filter(function (item) { return item.moduleAssets.status !== 'loading'; }); needLoadItems.forEach(function (item) { return item.moduleAssets.status = 'loading'; }); return moduleRetryLoad(needLoadItems).then(function () { needLoadItems.forEach(function (item) { item.moduleAssets.status = 'success'; if (!item.moduleAssets.ready) { item.result = getWrapperDataFromGlobal(item.moduleAssets.name); return; } item.moduleAssets.ready.apply(item.moduleAssets); item.result = getWrapperDataFromGlobal(item.moduleAssets.name); }); if (loadingItems.length > 0) { startLoad(jsAssets, isAssetsList, time + 1); return; } deferred.resolve(isAssetsList ? loadItems.map(function (item) { return item.result; }) : loadItems[0].result); }); }; var loadJsModule = function loadJsModule(jsAssets) { var isAssetsList = true; if (typeof jsAssets === 'string') { jsAssets = [jsAssets]; isAssetsList = false; } else if (isModuleAssets(jsAssets)) { addJsModule(jsAssets); jsAssets = [jsAssets.name]; isAssetsList = false; } var notFound = jsAssets.find(function (x) { return !cacheJsModules[x]; }); !!!notFound ? invariant(false, "Cannot found assets " + notFound) : void 0; startLoad(jsAssets, isAssetsList); return deferred.currentPromise; }; var cacheCssModules = {}; var addCssModule = function addCssModule(module) { !!module ? invariant(false, 'module cannot empty') : void 0; var name = module.name, loadUrls = module.loadUrls; !!name ? invariant(false, 'module name cannot empty') : void 0; !(!Array.isArray(loadUrls) || !loadUrls.length) ? invariant(false, 'module loadUrls cannot empty') : void 0; if (cacheCssModules[name]) { return false; } module.status = 'ready'; cacheCssModules[name] = module; return true; }; var startLoad$1 = function startLoad(cssAssets) { var loadItems = cssAssets.map(function (name) { var assets = cacheCssModules[name]; return { moduleAssets: assets, url: resloveCanUseUrl(assets) }; }); var needLoadItems = loadItems.filter(function (item) { return ['loading', 'success'].includes(item.moduleAssets.status); }); needLoadItems.forEach(function (item) { return item.moduleAssets.status = 'loading'; }); return moduleRetryLoad(needLoadItems).then(function () { needLoadItems.forEach(function (item) { item.moduleAssets.status = 'success'; }); }); }; /** * * @param cssAssets * @returns */ var loadCssAssets = function loadCssAssets(cssAssets) { var notFound = cssAssets.find(function (x) { return !cacheCssModules[x]; }); !!!notFound ? invariant(false, "Cannot found assets " + notFound) : void 0; startLoad$1(cssAssets); }; exports.loadjs = loadjs; exports.addCssModule = addCssModule; exports.addJsModule = addJsModule; exports.loadCssAssets = loadCssAssets; exports.loadJsModule = loadJsModule; exports.setBadUrlPrefixCacheOptions = setBadUrlPrefixCacheOptions; //# sourceMappingURL=static-assets-loader.cjs.development.js.map