@deleteagency/resource-loader
Advanced tools
Comparing version
@@ -1,2 +0,2 @@ | ||
!function(e,r){for(var t in r)e[t]=r[t]}(window,function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){"use strict";function n(e,r){for(var t=0;t<r.length;t++){var n=r[t];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}t.r(r);var o=function(){function e(){var r=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];!function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}(this,e),this._preloadedResources=t.map(function(e){return r._getResolvedResourceUrl(e)}),this._loadingResources={}}var r,t,o;return r=e,(t=[{key:"load",value:function(e){return Promise.all(e.map(this.loadResource.bind(this)))}},{key:"loadResource",value:function(e){return this._getLoadingPromise(e).then(function(e){return{status:"fulfilled",value:e}},function(e){return{status:"rejected",reason:e}})}},{key:"isResourceLoaded",value:function(e){var r=this;return 0!==this._preloadedResources.filter(function(t){return t===r._getResolvedResourceUrl(e)}).length||0!==window.performance.getEntriesByName(this._getResolvedResourceUrl(e),"resource").length&&(console.log("".concat(e," is already loaded")),!0)}},{key:"_getLoadingPromise",value:function(e){try{if(this.isResourceLoaded(e))return Promise.resolve();var r=this._findResourceNodeByUrl(e);return r?(console.log("".concat(e," is found as a node")),this._getLoadingPromiseFromNode(r,e)):this._loadResource(e)}catch(e){return Promise.reject(e)}}},{key:"_findResourceNodeByUrl",value:function(e){var r=this._getQuerySelectorByUrl(e),t=this._getResolvedResourceUrl(e);return e!==t&&(r+=",".concat(this._getQuerySelectorByUrl(t))),document.querySelector(r)}},{key:"_getQuerySelectorByUrl",value:function(e){switch(this._getResourceTypeByUrl(e)){case"script":return"".concat(this._getScriptSelector(e));case"styles":return"".concat(this._getStyleLinkSelector(e))}}},{key:"_getLoadingPromiseFromNode",value:function(e){return new Promise(function(r,t){e.addEventListener("load",function(e){r()}),e.addEventListener("error",function(e){t(e)})})}},{key:"_loadResource",value:function(e){var r=this;console.log("".concat(e," will be inserted"));var t=this._getResolvedResourceUrl(e);if(!(t in this._loadingResources)){var n=this._getLoadingPromiseOfInsertion(t);this._loadingResources[t]=n;var o=function(){return delete r._loadingResources[t]};n.then(o,o)}return this._loadingResources[t]}},{key:"_getLoadingPromiseOfInsertion",value:function(e){var r=null;switch(this._getResourceTypeByUrl(e)){case"script":r=this._insertScript(e);break;case"styles":r=this._insertStyleLink(e)}return this._getLoadingPromiseFromNode(r)}},{key:"_getResolvedResourceUrl",value:function(e){return this._resolvingAnchor||(this._resolvingAnchor=document.createElement("a")),this._resolvingAnchor.href=e,this._resolvingAnchor.href}},{key:"_getResourceTypeByUrl",value:function(e){if(e.match(/.\.css$/))return"styles";if(e.match(/.\.js$/))return"script";throw new Error("The type of resource ".concat(e," could not be recognized"))}},{key:"_insertScript",value:function(e){var r=document.createElement("script");r.async=!0,r.defer=!0,r.src=e;var t=document.getElementsByTagName("script")[0];return t.parentNode.insertBefore(r,t),r}},{key:"_insertStyleLink",value:function(e){var r=document.createElement("link");return r.rel="stylesheet",r.href=e,document.head.insertAdjacentElement("beforeend",r),r}},{key:"_getScriptSelector",value:function(e){return'script[src="'.concat(e,'"]')}},{key:"_getStyleLinkSelector",value:function(e){return'link[href="'.concat(e,'"]')}}])&&n(r.prototype,t),o&&n(r,o),e}();t.d(r,"resourceLoader",function(){return i});var i=new o}])); | ||
!function(e,t){for(var r in t)e[r]=t[r]}(window,function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}r.r(t);var o=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this._loadingResources={},this.setPreloadedResources(t)}var t,r,o;return t=e,(r=[{key:"setPreloadedResources",value:function(e){var t=this;this._preloadedResources=e.map(function(e){return t._getResolvedResourceUrl(e)})}},{key:"setDebug",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this._debug=e}},{key:"load",value:function(e){return Promise.all(e.map(this.loadResource.bind(this)))}},{key:"loadResource",value:function(e){return this._getLoadingPromise(e).then(function(e){return{status:"fulfilled",value:e}},function(e){return{status:"rejected",reason:e}})}},{key:"isResourceLoaded",value:function(e){var t=this;return 0!==this._preloadedResources.filter(function(r){return r===t._getResolvedResourceUrl(e)}).length||0!==window.performance.getEntriesByName(this._getResolvedResourceUrl(e),"resource").length&&(this._debug&&console.log("".concat(e," is already loaded")),!0)}},{key:"_getLoadingPromise",value:function(e){try{if(this.isResourceLoaded(e))return Promise.resolve();var t=this._findResourceNodeByUrl(e);return t?(this._debug&&console.log("".concat(e," is found as a node")),this._getLoadingPromiseFromNode(t,e)):this._loadResource(e)}catch(e){return Promise.reject(e)}}},{key:"_findResourceNodeByUrl",value:function(e){var t=this._getQuerySelectorByUrl(e),r=this._getResolvedResourceUrl(e);return e!==r&&(t+=",".concat(this._getQuerySelectorByUrl(r))),document.querySelector(t)}},{key:"_getQuerySelectorByUrl",value:function(e){switch(this._getResourceTypeByUrl(e)){case"script":return"".concat(this._getScriptSelector(e));case"styles":return"".concat(this._getStyleLinkSelector(e))}}},{key:"_getLoadingPromiseFromNode",value:function(e){return new Promise(function(t,r){e.addEventListener("load",function(e){t()}),e.addEventListener("error",function(e){r(e)})})}},{key:"_loadResource",value:function(e){var t=this;this._debug&&console.log("".concat(e," will be inserted"));var r=this._getResolvedResourceUrl(e);if(!(r in this._loadingResources)){var n=this._getLoadingPromiseOfInsertion(r);this._loadingResources[r]=n;var o=function(){return delete t._loadingResources[r]};n.then(o,o)}return this._loadingResources[r]}},{key:"_getLoadingPromiseOfInsertion",value:function(e){var t=null;switch(this._getResourceTypeByUrl(e)){case"script":t=this._insertScript(e);break;case"styles":t=this._insertStyleLink(e)}return this._getLoadingPromiseFromNode(t)}},{key:"_getResolvedResourceUrl",value:function(e){return this._resolvingAnchor||(this._resolvingAnchor=document.createElement("a")),this._resolvingAnchor.href=e,this._resolvingAnchor.href}},{key:"_getResourceTypeByUrl",value:function(e){if(e.match(/.\.css$/))return"styles";if(e.match(/.\.js$/))return"script";throw new Error("The type of resource ".concat(e," could not be recognized"))}},{key:"_insertScript",value:function(e){var t=document.createElement("script");t.async=!0,t.defer=!0,t.src=e;var r=document.getElementsByTagName("script")[0];return r.parentNode.insertBefore(t,r),t}},{key:"_insertStyleLink",value:function(e){var t=document.createElement("link");return t.rel="stylesheet",t.href=e,document.head.insertAdjacentElement("beforeend",t),t}},{key:"_getScriptSelector",value:function(e){return'script[src="'.concat(e,'"]')}},{key:"_getStyleLinkSelector",value:function(e){return'link[href="'.concat(e,'"]')}}])&&n(t.prototype,r),o&&n(t,o),e}();r.d(t,"resourceLoader",function(){return i});var i=new o}])); | ||
//# sourceMappingURL=resource-loader.min.js.map |
{ | ||
"name": "@deleteagency/resource-loader", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "", | ||
@@ -12,3 +12,2 @@ "main": "index.js", | ||
"watch": "webpack --watch", | ||
"server": "node docs/server.js", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
@@ -15,0 +14,0 @@ }, |
@@ -7,2 +7,4 @@ # Resource Loader | ||
[Live Demo](https://delete-agency.github.io/resource-loader/) | ||
## Motivation | ||
@@ -41,3 +43,3 @@ | ||
* { | ||
* resources: ["/accordion.css", "/accordion.js", "buttons.css"], | ||
* resources: ["/accordion.css", "/accordion.js", "/buttons.css"], | ||
* html: ` | ||
@@ -111,3 +113,24 @@ * <div data-accordion class="accordion"> | ||
### resourceLoader.setDebug(debug = true) | ||
Enable (or disable) debug mode for logging messages during loadResource() or load() about how and why a particular resource is going to be loaded | ||
#### debug | ||
*Required*<br> | ||
Type: `string`<br> | ||
Default: `true` | ||
Relative or absolute URL of the resource | ||
## Note | ||
There can be some cases when we can get stuck waiting for the loading of the particular resource forever after calling loadResource() or load(). | ||
It can happen when the desired resource is already rendered within the page and failed to load by the time we are trying to load them with resourceLoader. | ||
It happens because we rely on window.performance (Performance Timing API) which is inconsistent between browsers at the moment: | ||
some of the implementations (Safari, Chrome) don't add PerformanceResource entry when particular resource is failed to load (but they will in the future according to the issue above). | ||
More details here: https://github.com/w3c/resource-timing/issues/12. | ||
As a result we think that the resource is still loading and will be waiting forever because obviously load and error events are not gonna be triggered. | ||
These cases aren't covered at the moment and will likely be fixed after browsers have consistent Performance Timing API implementation | ||
## License | ||
[MIT](https://choosealicense.com/licenses/mit/) |
const RESOURCE_TYPE_SCRIPT = 'script'; | ||
const RESOURCE_TYPE_STYLES = 'styles'; | ||
/** | ||
* Note: There can be some cases when we are trying to get promise from node which was failed to load. | ||
* It happens because isResourceLoaded relies on window.performance (0Performance Timing API0 that is inconsistent between browsers at the moment: | ||
* https://github.com/w3c/resource-timing/issues/12 | ||
* Some of the implementations (Safari, Chrome) don't add PerformanceResource entry | ||
* when particular resource is failed (but they will in the future according to the issue above). | ||
* As a result we think that the resource is still loading and will be waiting forever | ||
* because obviously load and error events are not gonna be triggered. | ||
* These cases aren't covered at the moment and will likely be fixed after browsers have consistent Performance Timing API implementation | ||
*/ | ||
export default class ResourceLoader { | ||
constructor(preloadedResources = []) { | ||
this._preloadedResources = preloadedResources.map(url => this._getResolvedResourceUrl(url)); | ||
this._loadingResources = {}; | ||
this.setPreloadedResources(preloadedResources); | ||
} | ||
setPreloadedResources(preloadedResources) { | ||
this._preloadedResources = preloadedResources.map(url => this._getResolvedResourceUrl(url)); | ||
} | ||
/** | ||
* @param {boolean} debug | ||
*/ | ||
setDebug(debug = true) { | ||
this._debug = debug; | ||
} | ||
/** | ||
* @param {Array} resources | ||
@@ -62,3 +63,5 @@ * @return {Promise} | ||
if (loadedResource.length !== 0) { | ||
console.log(`${resourceUrl} is already loaded`); | ||
if (this._debug) { | ||
console.log(`${resourceUrl} is already loaded`); | ||
} | ||
return true; | ||
@@ -78,3 +81,5 @@ } | ||
if (node) { | ||
console.log(`${resourceUrl} is found as a node`); | ||
if (this._debug) { | ||
console.log(`${resourceUrl} is found as a node`); | ||
} | ||
return this._getLoadingPromiseFromNode(node, resourceUrl); | ||
@@ -120,3 +125,5 @@ } | ||
_loadResource(resourceUrl) { | ||
console.log(`${resourceUrl} will be inserted`); | ||
if (this._debug) { | ||
console.log(`${resourceUrl} will be inserted`); | ||
} | ||
const url = this._getResolvedResourceUrl(resourceUrl); | ||
@@ -123,0 +130,0 @@ // if not we should load it ourselves |
Sorry, the diff of this file is not supported yet
34010
2.84%196
3.16%133
20.91%