next
Version:
The React Framework
178 lines (176 loc) • 6.11 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.handleClientScriptLoad = handleClientScriptLoad;
exports.initScriptLoader = initScriptLoader;
exports.default = void 0;
var _extends = require("@swc/helpers/lib/_extends.js").default;
var _interop_require_wildcard = require("@swc/helpers/lib/_interop_require_wildcard.js").default;
var _object_without_properties_loose = require("@swc/helpers/lib/_object_without_properties_loose.js").default;
var _react = _interop_require_wildcard(require("react"));
var _headManagerContext = require("../shared/lib/head-manager-context");
var _headManager = require("./head-manager");
var _requestIdleCallback = require("./request-idle-callback");
const ScriptCache = new Map();
const LoadCache = new Set();
const ignoreProps = [
'onLoad',
'onReady',
'dangerouslySetInnerHTML',
'children',
'onError',
'strategy',
];
const loadScript = (props)=>{
const { src , id , onLoad =()=>{} , onReady =null , dangerouslySetInnerHTML , children ='' , strategy ='afterInteractive' , onError , } = props;
const cacheKey = id || src;
// Script has already loaded
if (cacheKey && LoadCache.has(cacheKey)) {
return;
}
// Contents of this script are already loading/loaded
if (ScriptCache.has(src)) {
LoadCache.add(cacheKey);
// Execute onLoad since the script loading has begun
ScriptCache.get(src).then(onLoad, onError);
return;
}
const el = document.createElement('script');
const loadPromise = new Promise((resolve, reject)=>{
el.addEventListener('load', function(e) {
resolve();
if (onLoad) {
onLoad.call(this, e);
}
// Run onReady for the first time after load event
if (onReady) {
onReady();
}
});
el.addEventListener('error', function(e) {
reject(e);
});
}).catch(function(e) {
if (onError) {
onError(e);
}
});
if (src) {
ScriptCache.set(src, loadPromise);
}
LoadCache.add(cacheKey);
if (dangerouslySetInnerHTML) {
el.innerHTML = dangerouslySetInnerHTML.__html || '';
} else if (children) {
el.textContent = typeof children === 'string' ? children : Array.isArray(children) ? children.join('') : '';
} else if (src) {
el.src = src;
}
for (const [k, value] of Object.entries(props)){
if (value === undefined || ignoreProps.includes(k)) {
continue;
}
const attr = _headManager.DOMAttributeNames[k] || k.toLowerCase();
el.setAttribute(attr, value);
}
if (strategy === 'worker') {
el.setAttribute('type', 'text/partytown');
}
el.setAttribute('data-nscript', strategy);
document.body.appendChild(el);
};
function handleClientScriptLoad(props) {
const { strategy ='afterInteractive' } = props;
if (strategy === 'lazyOnload') {
window.addEventListener('load', ()=>{
(0, _requestIdleCallback).requestIdleCallback(()=>loadScript(props));
});
} else {
loadScript(props);
}
}
function loadLazyScript(props) {
if (document.readyState === 'complete') {
(0, _requestIdleCallback).requestIdleCallback(()=>loadScript(props));
} else {
window.addEventListener('load', ()=>{
(0, _requestIdleCallback).requestIdleCallback(()=>loadScript(props));
});
}
}
function addBeforeInteractiveToCache() {
const scripts = [
...document.querySelectorAll('[data-nscript="beforeInteractive"]'),
...document.querySelectorAll('[data-nscript="beforePageRender"]'),
];
scripts.forEach((script)=>{
const cacheKey = script.id || script.getAttribute('src');
LoadCache.add(cacheKey);
});
}
function initScriptLoader(scriptLoaderItems) {
scriptLoaderItems.forEach(handleClientScriptLoad);
addBeforeInteractiveToCache();
}
function Script(props) {
const { id , src ='' , onLoad =()=>{} , onReady =null , strategy ='afterInteractive' , onError } = props, restProps = _object_without_properties_loose(props, [
"id",
"src",
"onLoad",
"onReady",
"strategy",
"onError"
]);
// Context is available only during SSR
const { updateScripts , scripts , getIsSsr } = (0, _react).useContext(_headManagerContext.HeadManagerContext);
(0, _react).useEffect(()=>{
const cacheKey = id || src;
// Run onReady if script has loaded before but component is re-mounted
if (onReady && cacheKey && LoadCache.has(cacheKey)) {
onReady();
}
}, [
onReady,
id,
src
]);
(0, _react).useEffect(()=>{
if (strategy === 'afterInteractive') {
loadScript(props);
} else if (strategy === 'lazyOnload') {
loadLazyScript(props);
}
}, [
props,
strategy
]);
if (strategy === 'beforeInteractive' || strategy === 'worker') {
if (updateScripts) {
scripts[strategy] = (scripts[strategy] || []).concat([
_extends({
id,
src,
onLoad,
onReady,
onError
}, restProps),
]);
updateScripts(scripts);
} else if (getIsSsr && getIsSsr()) {
// Script has already loaded during SSR
LoadCache.add(id || src);
} else if (getIsSsr && !getIsSsr()) {
loadScript(props);
}
}
return null;
}
var _default = Script;
exports.default = _default;
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=script.js.map
;