UNPKG

react-iammolina-cache-buster

Version:

This package allows clients to automatically check the new version when a new version is released in the production environment, and if a new version is published, clearing the cache and reload the page.

222 lines (189 loc) 7.57 kB
import { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { compare } from 'compare-versions'; function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } // A type of promise-like that resolves synchronously and supports only one observer const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator"; const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator"; // Asynchronously call a function and send errors to recovery continuation function _catch(body, recover) { try { var result = body(); } catch(e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } function CacheBuster(_ref) { var _ref$children = _ref.children, children = _ref$children === void 0 ? null : _ref$children, _ref$nowVersion = _ref.nowVersion, nowVersion = _ref$nowVersion === void 0 ? null : _ref$nowVersion, _ref$comparationVersi = _ref.comparationVersion, comparationVersion = _ref$comparationVersi === void 0 ? null : _ref$comparationVersi, _ref$isEnabled = _ref.isEnabled, isEnabled = _ref$isEnabled === void 0 ? false : _ref$isEnabled, _ref$isVerboseMode = _ref.isVerboseMode, isVerboseMode = _ref$isVerboseMode === void 0 ? false : _ref$isVerboseMode, _ref$loadingComponent = _ref.loadingComponent, loadingComponent = _ref$loadingComponent === void 0 ? null : _ref$loadingComponent, _ref$onCacheClear = _ref.onCacheClear, onCacheClear = _ref$onCacheClear === void 0 ? function () { return null; } : _ref$onCacheClear; var _useState = useState({ loading: true, isLatestVersion: false }), cacheStatus = _useState[0], setCacheStatus = _useState[1]; var log = function log(message, isError) { isVerboseMode && (isError ? console.error(message) : console.log(message)); }; var handleCurrentVersion = function handleCurrentVersion() { var _ref2; return (_ref2 = nowVersion != null ? nowVersion : window.localStorage.getItem('version')) != null ? _ref2 : false; }; var handleMetaVersion = function handleMetaVersion() { try { return Promise.resolve(_catch(function () { return comparationVersion ? comparationVersion : Promise.resolve(fetch('/meta.json')).then(function (res) { return Promise.resolve(res.json()).then(function (_ref3) { var metaVersion = _ref3.version; return metaVersion; }); }); }, function () { throw new Error('meta not read'); })); } catch (e) { return Promise.reject(e); } }; useEffect(function () { isEnabled ? checkCacheStatus() : log('React Cache Buster is disabled'); }, []); var checkCacheStatus = function checkCacheStatus() { try { var _temp3 = _catch(function () { return Promise.resolve(handleMetaVersion()).then(function (metaVersion) { if (!handleCurrentVersion()) { window.localStorage.setItem('version', metaVersion); } var currentVersion = handleCurrentVersion(); var shouldForceRefresh = isThereNewVersion(metaVersion, currentVersion); var _temp = function () { if (shouldForceRefresh) { log("There is a new version (v" + metaVersion + "). Should force refresh."); window.localStorage.setItem('version', metaVersion); return Promise.resolve(onCacheClear()).then(function () { return Promise.resolve(refreshCacheAndReload()).then(function () { setCacheStatus({ loading: false, isLatestVersion: false }); }); }); } else { log('There is no new version. No cache refresh needed.'); setCacheStatus({ loading: false, isLatestVersion: true }); } }(); if (_temp && _temp.then) return _temp.then(function () {}); }); }, function (error) { log('An error occurred while checking cache status.', true); log(error, true); setCacheStatus({ loading: false, isLatestVersion: true }); }); return Promise.resolve(_temp3 && _temp3.then ? _temp3.then(function () {}) : void 0); } catch (e) { return Promise.reject(e); } }; var isThereNewVersion = function isThereNewVersion(metaVersion, currentVersion) { log("meta(v" + metaVersion + ")."); log("current(v" + currentVersion + ")."); return compare(metaVersion, currentVersion, '>'); }; var refreshCacheAndReload = function refreshCacheAndReload() { try { return Promise.resolve(_catch(function () { var _temp4 = function () { var _window; if ((_window = window) !== null && _window !== void 0 && _window.caches) { var _window2 = window, caches = _window2.caches; return Promise.resolve(caches.keys()).then(function (cacheNames) { for (var _iterator = _createForOfIteratorHelperLoose(cacheNames), _step; !(_step = _iterator()).done;) { var cacheName = _step.value; caches["delete"](cacheName); } log('The cache has been deleted.'); window.location.reload(true); }); } }(); if (_temp4 && _temp4.then) return _temp4.then(function () {}); }, function (error) { log('An error occurred while deleting the cache.', true); log(error, true); })); } catch (e) { return Promise.reject(e); } }; if (cacheStatus.loading) { return loadingComponent; } return children; } CacheBuster.propTypes = { children: PropTypes.element.isRequired, nowVersion: PropTypes.string, comparationVersion: PropTypes.string, isEnabled: PropTypes.bool, isVerboseMode: PropTypes.bool, loadingComponent: PropTypes.element, onCacheClear: PropTypes.func }; export default CacheBuster;