react-frontload
Version:
Simple full stack data loading for React
1 lines • 12 kB
JavaScript
;var __assign=this&&this.__assign||function(){__assign=Object.assign||function(t){for(var s,i=1,n=arguments.length;i<n;i++){s=arguments[i];for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))t[p]=s[p]}return t};return __assign.apply(this,arguments)};var __awaiter=this&&this.__awaiter||function(thisArg,_arguments,P,generator){function adopt(value){return value instanceof P?value:new P(function(resolve){resolve(value)})}return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};var __generator=this&&this.__generator||function(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}};var __spreadArrays=this&&this.__spreadArrays||function(){for(var s=0,i=0,il=arguments.length;i<il;i++)s+=arguments[i].length;for(var r=Array(s),k=0,i=0;i<il;i++)for(var a=arguments[i],j=0,jl=a.length;j<jl;j++,k++)r[k]=a[j];return r};var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:true});exports.useFrontload=exports.frontloadServerRender=exports.FrontloadProvider=exports.createFrontloadState=void 0;var react_1=__importDefault(require("react"));var IS_SERVER=typeof window==="undefined"||!window.document||!window.document.createElement;var _log=("l"+"o"+"g"+"a").substring(0,3);var log=function(){var args=[];for(var _i=0;_i<arguments.length;_i++){args[_i]=arguments[_i]}console[_log].apply(console,args)};var runAllFrontloads=function(frontloads,context){return __awaiter(void 0,void 0,void 0,function(){var data;return __generator(this,function(_a){switch(_a.label){case 0:return[4,Promise.all(frontloads.map(function(_a){var fn=_a.fn;return fn(context)["catch"](function(error){return{_____FRONTLOAD_____isServerRenderError:true,error:error}})}))];case 1:data=_a.sent();return[2,data.map(function(data,i){return{key:frontloads[i].key,data:data}})]}})})};exports.createFrontloadState={server:function(args){return new FrontloadStatePrivate(args)},client:function(args){return new FrontloadStatePrivate(args)}};var FrontloadStatePrivate=function(){function FrontloadStatePrivate(_a){var _b=_a.serverRenderedData,serverRenderedData=_b===void 0?{}:_b,context=_a.context,logging=_a.logging;this.serverRender={pass:-1,frontloads:[],cache:{}};this.clientRender={isFirstRender:true,logging:false};this.serverRender.cache=serverRenderedData;this.context=context;this.clientRender.logging=!!logging}FrontloadStatePrivate.prototype.setFirstRenderDoneOnClient=function(){this.clientRender.isFirstRender=false;this.serverRender.cache={}};FrontloadStatePrivate.prototype.isFirstRender=function(){return this.clientRender.isFirstRender};FrontloadStatePrivate.prototype.isClientLoggingEnabled=function(){return this.clientRender.logging};FrontloadStatePrivate.prototype.prepareServerRenderPass=function(){this.serverRender.pass++;this.serverRender.frontloads.push([])};FrontloadStatePrivate.prototype.collectServerRenderFrontload=function(frontload){this.serverRender.frontloads[this.serverRender.pass].push(frontload)};FrontloadStatePrivate.prototype.hasFrontloadRunOnServer=function(key){return this.serverRender.cache.hasOwnProperty(key)};FrontloadStatePrivate.prototype.getFrontloadServerRenderedData=function(key){return this.serverRender.cache[key]};FrontloadStatePrivate.prototype.getServerRenderMeta=function(){return{numPasses:this.serverRender.pass+1,frontloads:Object.keys(this.serverRender.cache)}};FrontloadStatePrivate.prototype.getServerRenderCache=function(){return __assign({},this.serverRender.cache)};FrontloadStatePrivate.prototype.runFrontloadsForThisServerRenderPass=function(){return __awaiter(this,void 0,void 0,function(){var pass,allFrontloads,alreadySeenInCurrentPass,newFrontloads,duplicateFrontloads,cachedFrontloads,errorCachedFrontloads,errors,data;var _this=this;return __generator(this,function(_a){switch(_a.label){case 0:pass=this.serverRender.pass+0;allFrontloads=this.serverRender.frontloads[pass];alreadySeenInCurrentPass={};newFrontloads=[];duplicateFrontloads={};cachedFrontloads={};errorCachedFrontloads={};allFrontloads.forEach(function(frontload){var _a;if(frontload.key in _this.serverRender.cache){cachedFrontloads[frontload.key]=true;if((_a=_this.serverRender.cache[frontload.key])===null||_a===void 0?void 0:_a._____FRONTLOAD_____isServerRenderError){errorCachedFrontloads[frontload.key]=true}}else if(alreadySeenInCurrentPass[frontload.key]){duplicateFrontloads[frontload.key]++}else{alreadySeenInCurrentPass[frontload.key]=true;newFrontloads.push(frontload)}});errors={};return[4,runAllFrontloads(newFrontloads,this.context)];case 1:data=_a.sent();data.forEach(function(_a){var key=_a.key,data=_a.data;if(data===null||data===void 0?void 0:data._____FRONTLOAD_____isServerRenderError){errors[key]=data.error;_this.serverRender.cache[key]={_____FRONTLOAD_____isServerRenderError:true}}else{_this.serverRender.cache[key]=data}});return[2,{pass:pass,allFrontloads:allFrontloads,newFrontloads:newFrontloads,duplicateFrontloads:duplicateFrontloads,cachedFrontloads:cachedFrontloads,errorCachedFrontloads:errorCachedFrontloads,errors:errors}]}})})};return FrontloadStatePrivate}();var FrontloadContext=react_1.default.createContext(null);exports.FrontloadProvider=function(_a){var frontloadState=_a.initialState,children=_a.children;react_1.default.useEffect(function(){frontloadState.setFirstRenderDoneOnClient()},[]);return react_1.default.createElement(FrontloadContext.Provider,{value:frontloadState},children)};var LOG_MESSAGE_LINE="___________________________________\n";var spaces=function(length){return Array(length+1).join(" ")};var padRight=function(str,length){var buffer=spaces(length);return(str+buffer).substring(0,buffer.length)};function frontloadServerRender(_a){var render=_a.render,frontloadState=_a.frontloadState;return __awaiter(this,void 0,void 0,function(){var logging,_b,rendered,data,logMessage,err_1;return __generator(this,function(_c){switch(_c.label){case 0:logging=frontloadState.isClientLoggingEnabled();_c.label=1;case 1:_c.trys.push([1,3,,4]);return[4,_frontloadServerRender(render,frontloadState,logging,"",false)];case 2:_b=_c.sent(),rendered=_b.rendered,data=_b.data,logMessage=_b.logMessage;if(logging){log(logMessage)}return[2,{rendered:rendered,data:data}];case 3:err_1=_c.sent();if(logging){console.log(LOG_MESSAGE_LINE+"react-frontload server render trace\n\n"+"Error thrown during server render:\n\n",err_1);console.log("\n\n")}throw err_1;case 4:return[2]}})})}exports.frontloadServerRender=frontloadServerRender;function _frontloadServerRender(render,frontloadState,logging,logMessage,isFinalRender){return __awaiter(this,void 0,void 0,function(){var rendered,renderPassResult,seen_1,renderPassMessage,longest_1,serverRenderMeta;return __generator(this,function(_a){switch(_a.label){case 0:frontloadState.prepareServerRenderPass();rendered=render({isFinalRender:isFinalRender});return[4,frontloadState.runFrontloadsForThisServerRenderPass()];case 1:renderPassResult=_a.sent();Object.keys(renderPassResult.errors).forEach(function(key){console.error("\n[react-frontload] Error on frontload ["+key+"], render pass "+renderPassResult.pass+"\n\n",renderPassResult.errors[key],"\n")});if(logging){if(isFinalRender){logMessage+="\n∙ Render pass "+renderPassResult.pass+"\n"+" - final render pass, no frontloads ran\n"}else{seen_1={};renderPassMessage="Render pass "+renderPassResult.pass;longest_1=Math.max.apply(Math,__spreadArrays(renderPassResult.allFrontloads.map(function(_a){var key=_a.key;return key.length}),[renderPassMessage.length-2]))+2;logMessage+="\n∙ "+padRight(renderPassMessage,longest_1)+" | "+renderPassResult.allFrontloads.length+" total, "+renderPassResult.newFrontloads.length+" new\n";renderPassResult.allFrontloads.forEach(function(_a){var key=_a.key;var type="new";if(renderPassResult.duplicateFrontloads[key]&&seen_1[key]){type="duplicate"}else if(renderPassResult.cachedFrontloads[key]){type=renderPassResult.errorCachedFrontloads[key]?"error in previous pass":"cached"}else if(renderPassResult.errors[key]!==undefined){type="error"}logMessage+=" - "+padRight(key,longest_1)+"| "+type+"\n";seen_1[key]=true})}}if(renderPassResult.newFrontloads.length>0){return[2,_frontloadServerRender(render,frontloadState,logging,logMessage,isFinalRender)]}if(isFinalRender===false){return[2,_frontloadServerRender(render,frontloadState,logging,logMessage,true)]}if(logging){serverRenderMeta=frontloadState.getServerRenderMeta();logMessage=LOG_MESSAGE_LINE+"react-frontload server render trace\n\n"+(serverRenderMeta.frontloads.length+" frontloads ran in "+serverRenderMeta.numPasses+" render passes\n")+serverRenderMeta.frontloads.map(function(key){return" - "+key}).join("\n")+"\n"+logMessage+LOG_MESSAGE_LINE}return[2,{data:frontloadState.getServerRenderCache(),rendered:rendered,logMessage:logMessage}]}})})}var clientLogPrefix="[react-frontload]";function useFrontload(key,fn){var frontloadState=react_1.default.useContext(FrontloadContext);var serverRendered=frontloadState.isFirstRender();var pendingInitial=serverRendered?!frontloadState.hasFrontloadRunOnServer(key):true;var data=serverRendered?frontloadState.getFrontloadServerRenderedData(key):undefined;var error=!!(data===null||data===void 0?void 0:data._____FRONTLOAD_____isServerRenderError);var _a=react_1.default.useState({data:data,frontloadMeta:{serverRendered:serverRendered,pending:pendingInitial,done:!pendingInitial,error:error}}),state=_a[0],setState=_a[1];react_1.default.useEffect(function(){if(state.frontloadMeta.serverRendered){if(frontloadState.isClientLoggingEnabled())log(clientLogPrefix+" "+key+" | server rendered")}else{var start_1=0;if(frontloadState.isClientLoggingEnabled()){log(clientLogPrefix+" component ["+key+"] - running frontload");start_1=Date.now()}fn(frontloadState.context).then(function(data){if(frontloadState.isClientLoggingEnabled())log(clientLogPrefix+" "+key+" | frontload ran in "+(Date.now()-start_1)+"ms");setState(__assign(__assign({},state),{data:data,frontloadMeta:__assign(__assign({},state.frontloadMeta),{pending:false,done:true})}))}).catch(function(error){if(frontloadState.isClientLoggingEnabled())log(clientLogPrefix+" "+key+" | frontload errored in "+(Date.now()-start_1)+"ms");setState(__assign(__assign({},state),{frontloadMeta:__assign(__assign({},state.frontloadMeta),{pending:false,done:true,error:error})}))})}},[]);if(IS_SERVER){frontloadState.collectServerRenderFrontload({key:key,fn:fn})}return __assign(__assign({},state),{setData:function(fn){setState(function(state){return __assign(__assign({},state),{data:fn(state.data)})})}})}exports.useFrontload=useFrontload;