563 lines
16 KiB
JavaScript
563 lines
16 KiB
JavaScript
import React from 'react';
|
|
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';
|
|
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
import _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';
|
|
import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
|
|
import { isValidElementType } from 'react-is';
|
|
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
|
|
/* eslint-disable import/prefer-default-export */
|
|
function invariant(condition, message) {
|
|
if (condition) return;
|
|
var error = new Error("loadable: " + message);
|
|
error.framesToPop = 1;
|
|
error.name = 'Invariant Violation';
|
|
throw error;
|
|
}
|
|
function warn(message) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn("loadable: " + message);
|
|
}
|
|
|
|
var Context = /*#__PURE__*/
|
|
React.createContext();
|
|
|
|
var LOADABLE_REQUIRED_CHUNKS_KEY = '__LOADABLE_REQUIRED_CHUNKS__';
|
|
function getRequiredChunkKey(namespace) {
|
|
return "" + namespace + LOADABLE_REQUIRED_CHUNKS_KEY;
|
|
}
|
|
|
|
var sharedInternals = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
getRequiredChunkKey: getRequiredChunkKey,
|
|
invariant: invariant,
|
|
Context: Context
|
|
});
|
|
|
|
var LOADABLE_SHARED = {
|
|
initialChunks: {}
|
|
};
|
|
|
|
var STATUS_PENDING = 'PENDING';
|
|
var STATUS_RESOLVED = 'RESOLVED';
|
|
var STATUS_REJECTED = 'REJECTED';
|
|
|
|
function resolveConstructor(ctor) {
|
|
if (typeof ctor === 'function') {
|
|
return {
|
|
requireAsync: ctor,
|
|
resolve: function resolve() {
|
|
return undefined;
|
|
},
|
|
chunkName: function chunkName() {
|
|
return undefined;
|
|
}
|
|
};
|
|
}
|
|
|
|
return ctor;
|
|
}
|
|
|
|
var withChunkExtractor = function withChunkExtractor(Component) {
|
|
var LoadableWithChunkExtractor = function LoadableWithChunkExtractor(props) {
|
|
return React.createElement(Context.Consumer, null, function (extractor) {
|
|
return React.createElement(Component, Object.assign({
|
|
__chunkExtractor: extractor
|
|
}, props));
|
|
});
|
|
};
|
|
|
|
if (Component.displayName) {
|
|
LoadableWithChunkExtractor.displayName = Component.displayName + "WithChunkExtractor";
|
|
}
|
|
|
|
return LoadableWithChunkExtractor;
|
|
};
|
|
|
|
var identity = function identity(v) {
|
|
return v;
|
|
};
|
|
|
|
function createLoadable(_ref) {
|
|
var _ref$defaultResolveCo = _ref.defaultResolveComponent,
|
|
defaultResolveComponent = _ref$defaultResolveCo === void 0 ? identity : _ref$defaultResolveCo,
|
|
_render = _ref.render,
|
|
onLoad = _ref.onLoad;
|
|
|
|
function loadable(loadableConstructor, options) {
|
|
if (options === void 0) {
|
|
options = {};
|
|
}
|
|
|
|
var ctor = resolveConstructor(loadableConstructor);
|
|
var cache = {};
|
|
/**
|
|
* Cachekey represents the component to be loaded
|
|
* if key changes - component has to be reloaded
|
|
* @param props
|
|
* @returns {null|Component}
|
|
*/
|
|
|
|
function _getCacheKey(props) {
|
|
if (options.cacheKey) {
|
|
return options.cacheKey(props);
|
|
}
|
|
|
|
if (ctor.resolve) {
|
|
return ctor.resolve(props);
|
|
}
|
|
|
|
return 'static';
|
|
}
|
|
/**
|
|
* Resolves loaded `module` to a specific `Component
|
|
* @param module
|
|
* @param props
|
|
* @param Loadable
|
|
* @returns Component
|
|
*/
|
|
|
|
|
|
function resolve(module, props, Loadable) {
|
|
var Component = options.resolveComponent ? options.resolveComponent(module, props) : defaultResolveComponent(module);
|
|
|
|
if (options.resolveComponent && !isValidElementType(Component)) {
|
|
throw new Error("resolveComponent returned something that is not a React component!");
|
|
}
|
|
|
|
hoistNonReactStatics(Loadable, Component, {
|
|
preload: true
|
|
});
|
|
return Component;
|
|
}
|
|
|
|
var InnerLoadable =
|
|
/*#__PURE__*/
|
|
function (_React$Component) {
|
|
_inheritsLoose(InnerLoadable, _React$Component);
|
|
|
|
InnerLoadable.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {
|
|
var cacheKey = _getCacheKey(props);
|
|
|
|
return _extends({}, state, {
|
|
cacheKey: cacheKey,
|
|
// change of a key triggers loading state automatically
|
|
loading: state.loading || state.cacheKey !== cacheKey
|
|
});
|
|
};
|
|
|
|
function InnerLoadable(props) {
|
|
var _this;
|
|
|
|
_this = _React$Component.call(this, props) || this;
|
|
_this.state = {
|
|
result: null,
|
|
error: null,
|
|
loading: true,
|
|
cacheKey: _getCacheKey(props)
|
|
};
|
|
invariant(!props.__chunkExtractor || ctor.requireSync, 'SSR requires `@loadable/babel-plugin`, please install it'); // Server-side
|
|
|
|
if (props.__chunkExtractor) {
|
|
// This module has been marked with no SSR
|
|
if (options.ssr === false) {
|
|
return _assertThisInitialized(_this);
|
|
} // We run load function, we assume that it won't fail and that it
|
|
// triggers a synchronous loading of the module
|
|
|
|
|
|
ctor.requireAsync(props)["catch"](function () {
|
|
return null;
|
|
}); // So we can require now the module synchronously
|
|
|
|
_this.loadSync();
|
|
|
|
props.__chunkExtractor.addChunk(ctor.chunkName(props));
|
|
|
|
return _assertThisInitialized(_this);
|
|
} // Client-side with `isReady` method present (SSR probably)
|
|
// If module is already loaded, we use a synchronous loading
|
|
// Only perform this synchronous loading if the component has not
|
|
// been marked with no SSR, else we risk hydration mismatches
|
|
|
|
|
|
if (options.ssr !== false && ( // is ready - was loaded in this session
|
|
ctor.isReady && ctor.isReady(props) || // is ready - was loaded during SSR process
|
|
ctor.chunkName && LOADABLE_SHARED.initialChunks[ctor.chunkName(props)])) {
|
|
_this.loadSync();
|
|
}
|
|
|
|
return _this;
|
|
}
|
|
|
|
var _proto = InnerLoadable.prototype;
|
|
|
|
_proto.componentDidMount = function componentDidMount() {
|
|
this.mounted = true; // retrieve loading promise from a global cache
|
|
|
|
var cachedPromise = this.getCache(); // if promise exists, but rejected - clear cache
|
|
|
|
if (cachedPromise && cachedPromise.status === STATUS_REJECTED) {
|
|
this.setCache();
|
|
} // component might be resolved synchronously in the constructor
|
|
|
|
|
|
if (this.state.loading) {
|
|
this.loadAsync();
|
|
}
|
|
};
|
|
|
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
|
|
// Component has to be reloaded on cacheKey change
|
|
if (prevState.cacheKey !== this.state.cacheKey) {
|
|
this.loadAsync();
|
|
}
|
|
};
|
|
|
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
this.mounted = false;
|
|
};
|
|
|
|
_proto.safeSetState = function safeSetState(nextState, callback) {
|
|
if (this.mounted) {
|
|
this.setState(nextState, callback);
|
|
}
|
|
}
|
|
/**
|
|
* returns a cache key for the current props
|
|
* @returns {Component|string}
|
|
*/
|
|
;
|
|
|
|
_proto.getCacheKey = function getCacheKey() {
|
|
return _getCacheKey(this.props);
|
|
}
|
|
/**
|
|
* access the persistent cache
|
|
*/
|
|
;
|
|
|
|
_proto.getCache = function getCache() {
|
|
return cache[this.getCacheKey()];
|
|
}
|
|
/**
|
|
* sets the cache value. If called without value sets it as undefined
|
|
*/
|
|
;
|
|
|
|
_proto.setCache = function setCache(value) {
|
|
if (value === void 0) {
|
|
value = undefined;
|
|
}
|
|
|
|
cache[this.getCacheKey()] = value;
|
|
};
|
|
|
|
_proto.triggerOnLoad = function triggerOnLoad() {
|
|
var _this2 = this;
|
|
|
|
if (onLoad) {
|
|
setTimeout(function () {
|
|
onLoad(_this2.state.result, _this2.props);
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Synchronously loads component
|
|
* target module is expected to already exists in the module cache
|
|
* or be capable to resolve synchronously (webpack target=node)
|
|
*/
|
|
;
|
|
|
|
_proto.loadSync = function loadSync() {
|
|
// load sync is expecting component to be in the "loading" state already
|
|
// sounds weird, but loading=true is the initial state of InnerLoadable
|
|
if (!this.state.loading) return;
|
|
|
|
try {
|
|
var loadedModule = ctor.requireSync(this.props);
|
|
var result = resolve(loadedModule, this.props, Loadable);
|
|
this.state.result = result;
|
|
this.state.loading = false;
|
|
} catch (error) {
|
|
console.error('loadable-components: failed to synchronously load component, which expected to be available', {
|
|
fileName: ctor.resolve(this.props),
|
|
chunkName: ctor.chunkName(this.props),
|
|
error: error ? error.message : error
|
|
});
|
|
this.state.error = error;
|
|
}
|
|
}
|
|
/**
|
|
* Asynchronously loads a component.
|
|
*/
|
|
;
|
|
|
|
_proto.loadAsync = function loadAsync() {
|
|
var _this3 = this;
|
|
|
|
var promise = this.resolveAsync();
|
|
promise.then(function (loadedModule) {
|
|
var result = resolve(loadedModule, _this3.props, {
|
|
Loadable: Loadable
|
|
});
|
|
|
|
_this3.safeSetState({
|
|
result: result,
|
|
loading: false
|
|
}, function () {
|
|
return _this3.triggerOnLoad();
|
|
});
|
|
})["catch"](function (error) {
|
|
return _this3.safeSetState({
|
|
error: error,
|
|
loading: false
|
|
});
|
|
});
|
|
return promise;
|
|
}
|
|
/**
|
|
* Asynchronously resolves(not loads) a component.
|
|
* Note - this function does not change the state
|
|
*/
|
|
;
|
|
|
|
_proto.resolveAsync = function resolveAsync() {
|
|
var _this4 = this;
|
|
|
|
var _this$props = this.props,
|
|
__chunkExtractor = _this$props.__chunkExtractor,
|
|
forwardedRef = _this$props.forwardedRef,
|
|
props = _objectWithoutPropertiesLoose(_this$props, ["__chunkExtractor", "forwardedRef"]);
|
|
|
|
var promise = this.getCache();
|
|
|
|
if (!promise) {
|
|
promise = ctor.requireAsync(props);
|
|
promise.status = STATUS_PENDING;
|
|
this.setCache(promise);
|
|
promise.then(function () {
|
|
promise.status = STATUS_RESOLVED;
|
|
}, function (error) {
|
|
console.error('loadable-components: failed to asynchronously load component', {
|
|
fileName: ctor.resolve(_this4.props),
|
|
chunkName: ctor.chunkName(_this4.props),
|
|
error: error ? error.message : error
|
|
});
|
|
promise.status = STATUS_REJECTED;
|
|
});
|
|
}
|
|
|
|
return promise;
|
|
};
|
|
|
|
_proto.render = function render() {
|
|
var _this$props2 = this.props,
|
|
forwardedRef = _this$props2.forwardedRef,
|
|
propFallback = _this$props2.fallback,
|
|
__chunkExtractor = _this$props2.__chunkExtractor,
|
|
props = _objectWithoutPropertiesLoose(_this$props2, ["forwardedRef", "fallback", "__chunkExtractor"]);
|
|
|
|
var _this$state = this.state,
|
|
error = _this$state.error,
|
|
loading = _this$state.loading,
|
|
result = _this$state.result;
|
|
|
|
if (options.suspense) {
|
|
var cachedPromise = this.getCache() || this.loadAsync();
|
|
|
|
if (cachedPromise.status === STATUS_PENDING) {
|
|
throw this.loadAsync();
|
|
}
|
|
}
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
var fallback = propFallback || options.fallback || null;
|
|
|
|
if (loading) {
|
|
return fallback;
|
|
}
|
|
|
|
return _render({
|
|
fallback: fallback,
|
|
result: result,
|
|
options: options,
|
|
props: _extends({}, props, {
|
|
ref: forwardedRef
|
|
})
|
|
});
|
|
};
|
|
|
|
return InnerLoadable;
|
|
}(React.Component);
|
|
|
|
var EnhancedInnerLoadable = withChunkExtractor(InnerLoadable);
|
|
var Loadable = React.forwardRef(function (props, ref) {
|
|
return React.createElement(EnhancedInnerLoadable, Object.assign({
|
|
forwardedRef: ref
|
|
}, props));
|
|
});
|
|
Loadable.displayName = 'Loadable'; // In future, preload could use `<link rel="preload">`
|
|
|
|
Loadable.preload = function (props) {
|
|
ctor.requireAsync(props);
|
|
};
|
|
|
|
Loadable.load = function (props) {
|
|
return ctor.requireAsync(props);
|
|
};
|
|
|
|
return Loadable;
|
|
}
|
|
|
|
function lazy(ctor, options) {
|
|
return loadable(ctor, _extends({}, options, {
|
|
suspense: true
|
|
}));
|
|
}
|
|
|
|
return {
|
|
loadable: loadable,
|
|
lazy: lazy
|
|
};
|
|
}
|
|
|
|
function defaultResolveComponent(loadedModule) {
|
|
// eslint-disable-next-line no-underscore-dangle
|
|
return loadedModule.__esModule ? loadedModule["default"] : loadedModule["default"] || loadedModule;
|
|
}
|
|
|
|
/* eslint-disable no-use-before-define, react/no-multi-comp */
|
|
|
|
var _createLoadable =
|
|
/*#__PURE__*/
|
|
createLoadable({
|
|
defaultResolveComponent: defaultResolveComponent,
|
|
render: function render(_ref) {
|
|
var Component = _ref.result,
|
|
props = _ref.props;
|
|
return React.createElement(Component, props);
|
|
}
|
|
}),
|
|
loadable = _createLoadable.loadable,
|
|
lazy = _createLoadable.lazy;
|
|
|
|
/* eslint-disable no-use-before-define, react/no-multi-comp */
|
|
|
|
var _createLoadable$1 =
|
|
/*#__PURE__*/
|
|
createLoadable({
|
|
onLoad: function onLoad(result, props) {
|
|
if (result && props.forwardedRef) {
|
|
if (typeof props.forwardedRef === 'function') {
|
|
props.forwardedRef(result);
|
|
} else {
|
|
props.forwardedRef.current = result;
|
|
}
|
|
}
|
|
},
|
|
render: function render(_ref) {
|
|
var result = _ref.result,
|
|
props = _ref.props;
|
|
|
|
if (props.children) {
|
|
return props.children(result);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}),
|
|
loadable$1 = _createLoadable$1.loadable,
|
|
lazy$1 = _createLoadable$1.lazy;
|
|
|
|
/* eslint-disable no-underscore-dangle, camelcase */
|
|
var BROWSER = typeof window !== 'undefined';
|
|
function loadableReady(done, _temp) {
|
|
if (done === void 0) {
|
|
done = function done() {};
|
|
}
|
|
|
|
var _ref = _temp === void 0 ? {} : _temp,
|
|
_ref$namespace = _ref.namespace,
|
|
namespace = _ref$namespace === void 0 ? '' : _ref$namespace,
|
|
_ref$chunkLoadingGlob = _ref.chunkLoadingGlobal,
|
|
chunkLoadingGlobal = _ref$chunkLoadingGlob === void 0 ? '__LOADABLE_LOADED_CHUNKS__' : _ref$chunkLoadingGlob;
|
|
|
|
if (!BROWSER) {
|
|
warn('`loadableReady()` must be called in browser only');
|
|
done();
|
|
return Promise.resolve();
|
|
}
|
|
|
|
var requiredChunks = null;
|
|
|
|
if (BROWSER) {
|
|
var id = getRequiredChunkKey(namespace);
|
|
var dataElement = document.getElementById(id);
|
|
|
|
if (dataElement) {
|
|
requiredChunks = JSON.parse(dataElement.textContent);
|
|
var extElement = document.getElementById(id + "_ext");
|
|
|
|
if (extElement) {
|
|
var _JSON$parse = JSON.parse(extElement.textContent),
|
|
namedChunks = _JSON$parse.namedChunks;
|
|
|
|
namedChunks.forEach(function (chunkName) {
|
|
LOADABLE_SHARED.initialChunks[chunkName] = true;
|
|
});
|
|
} else {
|
|
// version mismatch
|
|
throw new Error('loadable-component: @loadable/server does not match @loadable/component');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!requiredChunks) {
|
|
warn('`loadableReady()` requires state, please use `getScriptTags` or `getScriptElements` server-side');
|
|
done();
|
|
return Promise.resolve();
|
|
}
|
|
|
|
var resolved = false;
|
|
return new Promise(function (resolve) {
|
|
window[chunkLoadingGlobal] = window[chunkLoadingGlobal] || [];
|
|
var loadedChunks = window[chunkLoadingGlobal];
|
|
var originalPush = loadedChunks.push.bind(loadedChunks);
|
|
|
|
function checkReadyState() {
|
|
if (requiredChunks.every(function (chunk) {
|
|
return loadedChunks.some(function (_ref2) {
|
|
var chunks = _ref2[0];
|
|
return chunks.indexOf(chunk) > -1;
|
|
});
|
|
})) {
|
|
if (!resolved) {
|
|
resolved = true;
|
|
resolve();
|
|
}
|
|
}
|
|
}
|
|
|
|
loadedChunks.push = function () {
|
|
originalPush.apply(void 0, arguments);
|
|
checkReadyState();
|
|
};
|
|
|
|
checkReadyState();
|
|
}).then(done);
|
|
}
|
|
|
|
/* eslint-disable no-underscore-dangle */
|
|
var loadable$2 = loadable;
|
|
loadable$2.lib = loadable$1;
|
|
var lazy$2 = lazy;
|
|
lazy$2.lib = lazy$1;
|
|
var __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = sharedInternals;
|
|
|
|
export default loadable$2;
|
|
export { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, lazy$2 as lazy, loadableReady };
|