From 3017155867187bda16fba2debcd7e43402cbf661 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Wed, 7 Jul 2021 14:18:37 +0800 Subject: [PATCH 1/3] Don't lazy-load components in ErrorBoundary We currently handle major errors through ErrorBoundary. If the error is network related, ErrorBoundary ends up blank if it's components are lazy-loaded. #codesplit --- ui/component/errorBoundary/view.jsx | 51 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/ui/component/errorBoundary/view.jsx b/ui/component/errorBoundary/view.jsx index 65e090fe8..6e10fc5bb 100644 --- a/ui/component/errorBoundary/view.jsx +++ b/ui/component/errorBoundary/view.jsx @@ -1,15 +1,14 @@ // @flow import type { Node } from 'react'; import React from 'react'; +import Yrbl from 'component/yrbl'; +import Button from 'component/button'; import { withRouter } from 'react-router'; import analytics from 'analytics'; +import I18nMessage from 'component/i18nMessage'; import Native from 'native'; import { Lbry } from 'lbry-redux'; -const Button = React.lazy(() => import('component/button' /* webpackChunkName: "button" */)); -const I18nMessage = React.lazy(() => import('component/i18nMessage' /* webpackChunkName: "i18nMessage" */)); -const Yrbl = React.lazy(() => import('component/yrbl' /* webpackChunkName: "yrbl" */)); - type Props = { children: Node, history: { @@ -75,29 +74,27 @@ class ErrorBoundary extends React.Component { if (hasError) { return (
- - - ), - }} - > - There was an error. Try %refreshing_the_app_link% to fix it. If that doesn't work, try pressing - Ctrl+R/Cmd+R. - - } - /> - + + ), + }} + > + There was an error. Try %refreshing_the_app_link% to fix it. If that doesn't work, try pressing + Ctrl+R/Cmd+R. + + } + /> {!errorWasReported && (
-- 2.45.2 From b326ad4ec10959e8edeeb1d0b36a5d6a13f773d9 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Wed, 7 Jul 2021 14:24:13 +0800 Subject: [PATCH 2/3] Ensure index.html isn't cached Part of the solution to handle `ChunkLoadError` in code-splitting. https://raphael-leger.medium.com/react-webpack-chunkloaderror-loading-chunk-x-failed-ac385bd110e0 #codesplit --- static/index-web.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/static/index-web.html b/static/index-web.html index b9ffe6fd2..9776b34ff 100644 --- a/static/index-web.html +++ b/static/index-web.html @@ -3,6 +3,8 @@ + + -- 2.45.2 From 67324aca210d05c32db2ad3792e96a1acb1dd70c Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Wed, 7 Jul 2021 15:10:28 +0800 Subject: [PATCH 3/3] Reload page when trying to open stale chunks https://raphael-leger.medium.com/react-webpack-chunkloaderror-loading-chunk-x-failed-ac385bd110e0 #codesplit --- ui/component/app/view.jsx | 31 +++---- ui/component/claimPreview/view.jsx | 5 +- ui/component/fileRender/view.jsx | 9 +- ui/component/page/view.jsx | 3 +- ui/component/router/view.jsx | 111 ++++++++++++------------- ui/component/wunderbar/view.jsx | 9 +- ui/modal/modalRouter/view.jsx | 127 ++++++++++------------------- ui/page/file/view.jsx | 3 +- ui/page/show/view.jsx | 11 ++- ui/util/lazyImport.js | 23 ++++++ 10 files changed, 148 insertions(+), 184 deletions(-) create mode 100644 ui/util/lazyImport.js diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx index 2493db4b0..f085eb81d 100644 --- a/ui/component/app/view.jsx +++ b/ui/component/app/view.jsx @@ -1,6 +1,7 @@ // @flow import * as PAGES from 'constants/pages'; import React, { useEffect, useRef, useState, useLayoutEffect } from 'react'; +import { lazyImport } from 'util/lazyImport'; import classnames from 'classnames'; import analytics from 'analytics'; import { buildURI, parseURI } from 'lbry-redux'; @@ -30,29 +31,21 @@ import { // @endif import LANGUAGE_MIGRATIONS from 'constants/language-migrations'; -const FileDrop = React.lazy(() => import('component/fileDrop' /* webpackChunkName: "secondary" */)); -const ModalRouter = React.lazy(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */)); -const Nag = React.lazy(() => import('component/common/nag' /* webpackChunkName: "secondary" */)); -const NagContinueFirstRun = React.lazy(() => - import('component/nagContinueFirstRun' /* webpackChunkName: "secondary" */) -); -const OpenInAppLink = React.lazy(() => import('web/component/openInAppLink' /* webpackChunkName: "secondary" */)); +const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "secondary" */)); +const ModalRouter = lazyImport(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */)); +const Nag = lazyImport(() => import('component/common/nag' /* webpackChunkName: "secondary" */)); +const NagContinueFirstRun = lazyImport(() => import('component/nagContinueFirstRun' /* webpackChunkName: "secondary" */)); +const OpenInAppLink = lazyImport(() => import('web/component/openInAppLink' /* webpackChunkName: "secondary" */)); // @if TARGET='web' -const NagDataCollection = React.lazy(() => - import('web/component/nag-data-collection' /* webpackChunkName: "secondary" */) -); -const NagDegradedPerformance = React.lazy(() => - import('web/component/nag-degraded-performance' /* webpackChunkName: "secondary" */) -); -const NagNoUser = React.lazy(() => import('web/component/nag-no-user' /* webpackChunkName: "nag-no-user" */)); -const YoutubeWelcome = React.lazy(() => - import('web/component/youtubeReferralWelcome' /* webpackChunkName: "secondary" */) -); +const NagDataCollection = lazyImport(() => import('web/component/nag-data-collection' /* webpackChunkName: "secondary" */)); +const NagDegradedPerformance = lazyImport(() => import('web/component/nag-degraded-performance' /* webpackChunkName: "secondary" */)); +const NagNoUser = lazyImport(() => import('web/component/nag-no-user' /* webpackChunkName: "nag-no-user" */)); +const YoutubeWelcome = lazyImport(() => import('web/component/youtubeReferralWelcome' /* webpackChunkName: "secondary" */)); // @endif -const SyncFatalError = React.lazy(() => import('component/syncFatalError' /* webpackChunkName: "syncFatalError" */)); -const Yrbl = React.lazy(() => import('component/yrbl' /* webpackChunkName: "yrbl" */)); +const SyncFatalError = lazyImport(() => import('component/syncFatalError' /* webpackChunkName: "syncFatalError" */)); +const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */)); // **************************************************************************** diff --git a/ui/component/claimPreview/view.jsx b/ui/component/claimPreview/view.jsx index a14a1e6e7..f787ea852 100644 --- a/ui/component/claimPreview/view.jsx +++ b/ui/component/claimPreview/view.jsx @@ -2,6 +2,7 @@ import type { Node } from 'react'; import React, { useEffect, forwardRef } from 'react'; import { NavLink, withRouter } from 'react-router-dom'; +import { lazyImport } from 'util/lazyImport'; import classnames from 'classnames'; import { parseURI, COLLECTIONS_CONSTS } from 'lbry-redux'; import { formatLbryUrlForWeb } from 'util/url'; @@ -27,9 +28,7 @@ import { ENABLE_NO_SOURCE_CLAIMS } from 'config'; import Button from 'component/button'; import * as ICONS from 'constants/icons'; -const AbandonedChannelPreview = React.lazy(() => - import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */) -); +const AbandonedChannelPreview = lazyImport(() => import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)); type Props = { uri: string, diff --git a/ui/component/fileRender/view.jsx b/ui/component/fileRender/view.jsx index 97fa79ad8..ec50e8007 100644 --- a/ui/component/fileRender/view.jsx +++ b/ui/component/fileRender/view.jsx @@ -1,6 +1,7 @@ // @flow import { remote } from 'electron'; import React from 'react'; +import { lazyImport } from 'util/lazyImport'; import classnames from 'classnames'; import * as RENDER_MODES from 'constants/file_render_modes'; import VideoViewer from 'component/viewers/videoViewer'; @@ -17,10 +18,10 @@ import ComicBookViewer from 'component/viewers/comicBookViewer'; import ThreeViewer from 'component/viewers/threeViewer'; // @endif -const AppViewer = React.lazy(() => import('component/viewers/appViewer' /* webpackChunkName: "appViewer" */)); -const HtmlViewer = React.lazy(() => import('component/viewers/htmlViewer' /* webpackChunkName: "htmlViewer" */)); -const ImageViewer = React.lazy(() => import('component/viewers/imageViewer' /* webpackChunkName: "imageViewer" */)); -const PdfViewer = React.lazy(() => import('component/viewers/pdfViewer' /* webpackChunkName: "pdfViewer" */)); +const AppViewer = lazyImport(() => import('component/viewers/appViewer' /* webpackChunkName: "appViewer" */)); +const HtmlViewer = lazyImport(() => import('component/viewers/htmlViewer' /* webpackChunkName: "htmlViewer" */)); +const ImageViewer = lazyImport(() => import('component/viewers/imageViewer' /* webpackChunkName: "imageViewer" */)); +const PdfViewer = lazyImport(() => import('component/viewers/pdfViewer' /* webpackChunkName: "pdfViewer" */)); type Props = { uri: string, diff --git a/ui/component/page/view.jsx b/ui/component/page/view.jsx index 299f5b06b..d6da4597b 100644 --- a/ui/component/page/view.jsx +++ b/ui/component/page/view.jsx @@ -2,6 +2,7 @@ import type { Node } from 'react'; import React, { Fragment } from 'react'; import classnames from 'classnames'; +import { lazyImport } from 'util/lazyImport'; import SideNavigation from 'component/sideNavigation'; import Header from 'component/header'; /* @if TARGET='app' */ @@ -12,7 +13,7 @@ import { useHistory } from 'react-router'; import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize'; import { parseURI } from 'lbry-redux'; -const Footer = React.lazy(() => import('web/component/footer' /* webpackChunkName: "secondary" */)); +const Footer = lazyImport(() => import('web/component/footer' /* webpackChunkName: "secondary" */)); export const MAIN_CLASS = 'main'; type Props = { diff --git a/ui/component/router/view.jsx b/ui/component/router/view.jsx index 2f8689d73..c84483ea4 100644 --- a/ui/component/router/view.jsx +++ b/ui/component/router/view.jsx @@ -3,6 +3,7 @@ import React, { useEffect } from 'react'; import { Route, Redirect, Switch, withRouter } from 'react-router-dom'; import * as PAGES from 'constants/pages'; +import { lazyImport } from 'util/lazyImport'; import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment'; import { parseURI, isURIValid } from 'lbry-redux'; import { SITE_TITLE, WELCOME_VERSION, SIMPLE_SITE } from 'config'; @@ -11,75 +12,67 @@ import LoadingBarOneOff from 'component/loadingBarOneOff'; import HomePage from 'page/home'; // @if TARGET='app' -const BackupPage = React.lazy(() => import('page/backup' /* webpackChunkName: "backup" */)); +const BackupPage = lazyImport(() => import('page/backup' /* webpackChunkName: "backup" */)); // @endif // @if TARGET='web' -const Code2257Page = React.lazy(() => import('web/page/code2257')); +const Code2257Page = lazyImport(() => import('web/page/code2257' /* webpackChunkName: "code2257" */)); // @endif // Chunk: "secondary" -const SignInPage = React.lazy(() => import('page/signIn' /* webpackChunkName: "secondary" */)); -const SignInWalletPasswordPage = React.lazy(() => - import('page/signInWalletPassword' /* webpackChunkName: "secondary" */) -); -const SignUpPage = React.lazy(() => import('page/signUp' /* webpackChunkName: "secondary" */)); -const SignInVerifyPage = React.lazy(() => import('page/signInVerify' /* webpackChunkName: "secondary" */)); +const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "secondary" */)); +const SignInWalletPasswordPage = lazyImport(() => import('page/signInWalletPassword' /* webpackChunkName: "secondary" */)); +const SignUpPage = lazyImport(() => import('page/signUp' /* webpackChunkName: "secondary" */)); +const SignInVerifyPage = lazyImport(() => import('page/signInVerify' /* webpackChunkName: "secondary" */)); // Chunk: "wallet/secondary" -const BuyPage = React.lazy(() => import('page/buy' /* webpackChunkName: "secondary" */)); -const ReceivePage = React.lazy(() => import('page/receive' /* webpackChunkName: "secondary" */)); -const SendPage = React.lazy(() => import('page/send' /* webpackChunkName: "secondary" */)); -const SwapPage = React.lazy(() => import('page/swap' /* webpackChunkName: "secondary" */)); -const WalletPage = React.lazy(() => import('page/wallet' /* webpackChunkName: "secondary" */)); +const BuyPage = lazyImport(() => import('page/buy' /* webpackChunkName: "secondary" */)); +const ReceivePage = lazyImport(() => import('page/receive' /* webpackChunkName: "secondary" */)); +const SendPage = lazyImport(() => import('page/send' /* webpackChunkName: "secondary" */)); +const SwapPage = lazyImport(() => import('page/swap' /* webpackChunkName: "secondary" */)); +const WalletPage = lazyImport(() => import('page/wallet' /* webpackChunkName: "secondary" */)); // Chunk: none -const NotificationsPage = React.lazy(() => import('page/notifications' /* webpackChunkName: "secondary" */)); -const CollectionPage = React.lazy(() => import('page/collection' /* webpackChunkName: "secondary" */)); -const ChannelNew = React.lazy(() => import('page/channelNew' /* webpackChunkName: "secondary" */)); -const ChannelsFollowingDiscoverPage = React.lazy(() => - import('page/channelsFollowingDiscover' /* webpackChunkName: "secondary" */) -); -const ChannelsFollowingPage = React.lazy(() => import('page/channelsFollowing' /* webpackChunkName: "secondary" */)); -const ChannelsPage = React.lazy(() => import('page/channels' /* webpackChunkName: "secondary" */)); -const CheckoutPage = React.lazy(() => import('page/checkoutPage' /* webpackChunkName: "checkoutPage" */)); -const CreatorDashboard = React.lazy(() => import('page/creatorDashboard' /* webpackChunkName: "secondary" */)); -const DiscoverPage = React.lazy(() => import('page/discover' /* webpackChunkName: "secondary" */)); -const EmbedWrapperPage = React.lazy(() => import('page/embedWrapper' /* webpackChunkName: "secondary" */)); -const FileListPublished = React.lazy(() => import('page/fileListPublished' /* webpackChunkName: "secondary" */)); -const FourOhFourPage = React.lazy(() => import('page/fourOhFour' /* webpackChunkName: "fourOhFour" */)); -const HelpPage = React.lazy(() => import('page/help' /* webpackChunkName: "help" */)); -const InvitePage = React.lazy(() => import('page/invite' /* webpackChunkName: "secondary" */)); -const InvitedPage = React.lazy(() => import('page/invited' /* webpackChunkName: "secondary" */)); -const LibraryPage = React.lazy(() => import('page/library' /* webpackChunkName: "secondary" */)); -const ListBlockedPage = React.lazy(() => import('page/listBlocked' /* webpackChunkName: "secondary" */)); -const ListsPage = React.lazy(() => import('page/lists' /* webpackChunkName: "secondary" */)); -const LiveStreamSetupPage = React.lazy(() => import('page/livestreamSetup' /* webpackChunkName: "secondary" */)); -const LivestreamCurrentPage = React.lazy(() => import('page/livestreamCurrent' /* webpackChunkName: "secondary" */)); -const PasswordResetPage = React.lazy(() => import('page/passwordReset' /* webpackChunkName: "secondary" */)); -const PasswordSetPage = React.lazy(() => import('page/passwordSet' /* webpackChunkName: "secondary" */)); -const PublishPage = React.lazy(() => import('page/publish' /* webpackChunkName: "secondary" */)); -const ReportContentPage = React.lazy(() => import('page/reportContent' /* webpackChunkName: "secondary" */)); -const ReportPage = React.lazy(() => import('page/report' /* webpackChunkName: "secondary" */)); -const RepostNew = React.lazy(() => import('page/repost' /* webpackChunkName: "secondary" */)); -const RewardsPage = React.lazy(() => import('page/rewards' /* webpackChunkName: "secondary" */)); -const RewardsVerifyPage = React.lazy(() => import('page/rewardsVerify' /* webpackChunkName: "secondary" */)); -const SearchPage = React.lazy(() => import('page/search' /* webpackChunkName: "secondary" */)); -const SettingsAdvancedPage = React.lazy(() => import('page/settingsAdvanced' /* webpackChunkName: "secondary" */)); -const SettingsStripeCard = React.lazy(() => import('page/settingsStripeCard' /* webpackChunkName: "secondary" */)); -const SettingsCreatorPage = React.lazy(() => import('page/settingsCreator' /* webpackChunkName: "secondary" */)); -const SettingsNotificationsPage = React.lazy(() => - import('page/settingsNotifications' /* webpackChunkName: "secondary" */) -); -const SettingsPage = React.lazy(() => import('page/settings' /* webpackChunkName: "secondary" */)); -const ShowPage = React.lazy(() => import('page/show' /* webpackChunkName: "secondary" */)); -const TagsFollowingManagePage = React.lazy(() => - import('page/tagsFollowingManage' /* webpackChunkName: "secondary" */) -); -const TagsFollowingPage = React.lazy(() => import('page/tagsFollowing' /* webpackChunkName: "secondary" */)); -const TopPage = React.lazy(() => import('page/top' /* webpackChunkName: "secondary" */)); -const Welcome = React.lazy(() => import('page/welcome' /* webpackChunkName: "secondary" */)); -const YoutubeSyncPage = React.lazy(() => import('page/youtubeSync' /* webpackChunkName: "secondary" */)); +const NotificationsPage = lazyImport(() => import('page/notifications' /* webpackChunkName: "secondary" */)); +const CollectionPage = lazyImport(() => import('page/collection' /* webpackChunkName: "secondary" */)); +const ChannelNew = lazyImport(() => import('page/channelNew' /* webpackChunkName: "secondary" */)); +const ChannelsFollowingDiscoverPage = lazyImport(() => import('page/channelsFollowingDiscover' /* webpackChunkName: "secondary" */)); +const ChannelsFollowingPage = lazyImport(() => import('page/channelsFollowing' /* webpackChunkName: "secondary" */)); +const ChannelsPage = lazyImport(() => import('page/channels' /* webpackChunkName: "secondary" */)); +const CheckoutPage = lazyImport(() => import('page/checkoutPage' /* webpackChunkName: "checkoutPage" */)); +const CreatorDashboard = lazyImport(() => import('page/creatorDashboard' /* webpackChunkName: "secondary" */)); +const DiscoverPage = lazyImport(() => import('page/discover' /* webpackChunkName: "secondary" */)); +const EmbedWrapperPage = lazyImport(() => import('page/embedWrapper' /* webpackChunkName: "secondary" */)); +const FileListPublished = lazyImport(() => import('page/fileListPublished' /* webpackChunkName: "secondary" */)); +const FourOhFourPage = lazyImport(() => import('page/fourOhFour' /* webpackChunkName: "fourOhFour" */)); +const HelpPage = lazyImport(() => import('page/help' /* webpackChunkName: "help" */)); +const InvitePage = lazyImport(() => import('page/invite' /* webpackChunkName: "secondary" */)); +const InvitedPage = lazyImport(() => import('page/invited' /* webpackChunkName: "secondary" */)); +const LibraryPage = lazyImport(() => import('page/library' /* webpackChunkName: "secondary" */)); +const ListBlockedPage = lazyImport(() => import('page/listBlocked' /* webpackChunkName: "secondary" */)); +const ListsPage = lazyImport(() => import('page/lists' /* webpackChunkName: "secondary" */)); +const LiveStreamSetupPage = lazyImport(() => import('page/livestreamSetup' /* webpackChunkName: "secondary" */)); +const LivestreamCurrentPage = lazyImport(() => import('page/livestreamCurrent' /* webpackChunkName: "secondary" */)); +const PasswordResetPage = lazyImport(() => import('page/passwordReset' /* webpackChunkName: "secondary" */)); +const PasswordSetPage = lazyImport(() => import('page/passwordSet' /* webpackChunkName: "secondary" */)); +const PublishPage = lazyImport(() => import('page/publish' /* webpackChunkName: "secondary" */)); +const ReportContentPage = lazyImport(() => import('page/reportContent' /* webpackChunkName: "secondary" */)); +const ReportPage = lazyImport(() => import('page/report' /* webpackChunkName: "secondary" */)); +const RepostNew = lazyImport(() => import('page/repost' /* webpackChunkName: "secondary" */)); +const RewardsPage = lazyImport(() => import('page/rewards' /* webpackChunkName: "secondary" */)); +const RewardsVerifyPage = lazyImport(() => import('page/rewardsVerify' /* webpackChunkName: "secondary" */)); +const SearchPage = lazyImport(() => import('page/search' /* webpackChunkName: "secondary" */)); +const SettingsAdvancedPage = lazyImport(() => import('page/settingsAdvanced' /* webpackChunkName: "secondary" */)); +const SettingsStripeCard = lazyImport(() => import('page/settingsStripeCard' /* webpackChunkName: "secondary" */)); +const SettingsCreatorPage = lazyImport(() => import('page/settingsCreator' /* webpackChunkName: "secondary" */)); +const SettingsNotificationsPage = lazyImport(() => import('page/settingsNotifications' /* webpackChunkName: "secondary" */)); +const SettingsPage = lazyImport(() => import('page/settings' /* webpackChunkName: "secondary" */)); +const ShowPage = lazyImport(() => import('page/show' /* webpackChunkName: "secondary" */)); +const TagsFollowingManagePage = lazyImport(() => import('page/tagsFollowingManage' /* webpackChunkName: "secondary" */)); +const TagsFollowingPage = lazyImport(() => import('page/tagsFollowing' /* webpackChunkName: "secondary" */)); +const TopPage = lazyImport(() => import('page/top' /* webpackChunkName: "secondary" */)); +const Welcome = lazyImport(() => import('page/welcome' /* webpackChunkName: "secondary" */)); +const YoutubeSyncPage = lazyImport(() => import('page/youtubeSync' /* webpackChunkName: "secondary" */)); // Tell the browser we are handling scroll restoration if ('scrollRestoration' in history) { diff --git a/ui/component/wunderbar/view.jsx b/ui/component/wunderbar/view.jsx index 44aba217d..22fb78d20 100644 --- a/ui/component/wunderbar/view.jsx +++ b/ui/component/wunderbar/view.jsx @@ -1,13 +1,12 @@ // @flow import * as ICONS from 'constants/icons'; import React from 'react'; +import { lazyImport } from 'util/lazyImport'; import { useIsMobile } from 'effects/use-screensize'; -const Button = React.lazy(() => import('component/button' /* webpackChunkName: "button" */)); -const Icon = React.lazy(() => import('component/common/icon' /* webpackChunkName: "icon" */)); -const WunderbarSuggestions = React.lazy(() => - import('component/wunderbarSuggestions' /* webpackChunkName: "secondary" */) -); +const Button = lazyImport(() => import('component/button' /* webpackChunkName: "button" */)); +const Icon = lazyImport(() => import('component/common/icon' /* webpackChunkName: "icon" */)); +const WunderbarSuggestions = lazyImport(() => import('component/wunderbarSuggestions' /* webpackChunkName: "secondary" */)); type Props = { doOpenMobileSearch: (any) => void, diff --git a/ui/modal/modalRouter/view.jsx b/ui/modal/modalRouter/view.jsx index dfc34bbb7..5092a16f3 100644 --- a/ui/modal/modalRouter/view.jsx +++ b/ui/modal/modalRouter/view.jsx @@ -1,95 +1,50 @@ // @flow import React from 'react'; import { withRouter } from 'react-router'; +import { lazyImport } from 'util/lazyImport'; import * as MODALS from 'constants/modal_types'; import LoadingBarOneOff from 'component/loadingBarOneOff'; -const ModalAffirmPurchase = React.lazy(() => - import('modal/modalAffirmPurchase' /* webpackChunkName: "modalAffirmPurchase" */) -); -const ModalAutoGenerateThumbnail = React.lazy(() => - import('modal/modalAutoGenerateThumbnail' /* webpackChunkName: "modalAutoGenerateThumbnail" */) -); -const ModalAutoUpdateDownloaded = React.lazy(() => - import('modal/modalAutoUpdateDownloaded' /* webpackChunkName: "modalAutoUpdateDownloaded" */) -); -const ModalClaimCollectionAdd = React.lazy(() => - import('modal/modalClaimCollectionAdd' /* webpackChunkName: "modalClaimCollectionAdd" */) -); -const ModalCommentAcknowledgement = React.lazy(() => - import('modal/modalCommentAcknowledgement' /* webpackChunkName: "modalCommentAcknowledgement" */) -); -const ModalConfirmAge = React.lazy(() => import('modal/modalConfirmAge' /* webpackChunkName: "modalConfirmAge" */)); -const ModalConfirmThumbnailUpload = React.lazy(() => - import('modal/modalConfirmThumbnailUpload' /* webpackChunkName: "modalConfirmThumbnailUpload" */) -); -const ModalConfirmTransaction = React.lazy(() => - import('modal/modalConfirmTransaction' /* webpackChunkName: "modalConfirmTransaction" */) -); -const ModalDeleteCollection = React.lazy(() => - import('modal/modalRemoveCollection' /* webpackChunkName: "modalRemoveCollection" */) -); -const ModalDownloading = React.lazy(() => import('modal/modalDownloading' /* webpackChunkName: "modalDownloading" */)); -const ModalError = React.lazy(() => import('modal/modalError' /* webpackChunkName: "modalError" */)); -const ModalFileSelection = React.lazy(() => - import('modal/modalFileSelection' /* webpackChunkName: "modalFileSelection" */) -); -const ModalFileTimeout = React.lazy(() => import('modal/modalFileTimeout' /* webpackChunkName: "modalFileTimeout" */)); -const ModalFirstReward = React.lazy(() => import('modal/modalFirstReward' /* webpackChunkName: "modalFirstReward" */)); -const ModalFirstSubscription = React.lazy(() => - import('modal/modalFirstSubscription' /* webpackChunkName: "modalFirstSubscription" */) -); -const ModalImageUpload = React.lazy(() => import('modal/modalImageUpload' /* webpackChunkName: "modalImageUpload" */)); -const ModalMassTipsUnlock = React.lazy(() => - import('modal/modalMassTipUnlock' /* webpackChunkName: "modalMassTipUnlock" */) -); -const ModalMobileSearch = React.lazy(() => - import('modal/modalMobileSearch' /* webpackChunkName: "modalMobileSearch" */) -); -const ModalOpenExternalResource = React.lazy(() => - import('modal/modalOpenExternalResource' /* webpackChunkName: "modalOpenExternalResource" */) -); -const ModalPasswordUnsave = React.lazy(() => - import('modal/modalPasswordUnsave' /* webpackChunkName: "modalPasswordUnsave" */) -); -const ModalPhoneCollection = React.lazy(() => - import('modal/modalPhoneCollection' /* webpackChunkName: "modalPhoneCollection" */) -); -const ModalPublish = React.lazy(() => import('modal/modalPublish' /* webpackChunkName: "modalPublish" */)); -const ModalPublishPreview = React.lazy(() => - import('modal/modalPublishPreview' /* webpackChunkName: "modalPublishPreview" */) -); -const ModalRemoveBtcSwapAddress = React.lazy(() => - import('modal/modalRemoveBtcSwapAddress' /* webpackChunkName: "modalRemoveBtcSwapAddress" */) -); -const ModalRemoveFile = React.lazy(() => import('modal/modalRemoveFile' /* webpackChunkName: "modalRemoveFile" */)); -const ModalRevokeClaim = React.lazy(() => import('modal/modalRevokeClaim' /* webpackChunkName: "modalRevokeClaim" */)); -const ModalRewardCode = React.lazy(() => import('modal/modalRewardCode' /* webpackChunkName: "modalRewardCode" */)); -const ModalSendTip = React.lazy(() => import('modal/modalSendTip' /* webpackChunkName: "modalSendTip" */)); -const ModalSetReferrer = React.lazy(() => import('modal/modalSetReferrer' /* webpackChunkName: "modalSetReferrer" */)); -const ModalSignOut = React.lazy(() => import('modal/modalSignOut' /* webpackChunkName: "modalSignOut" */)); -const ModalSocialShare = React.lazy(() => import('modal/modalSocialShare' /* webpackChunkName: "modalSocialShare" */)); -const ModalSupportsLiquidate = React.lazy(() => - import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */) -); -const ModalSyncEnable = React.lazy(() => import('modal/modalSyncEnable' /* webpackChunkName: "modalSyncEnable" */)); -const ModalTransactionFailed = React.lazy(() => - import('modal/modalTransactionFailed' /* webpackChunkName: "modalTransactionFailed" */) -); -const ModalUpgrade = React.lazy(() => import('modal/modalUpgrade' /* webpackChunkName: "modalUpgrade" */)); -const ModalViewImage = React.lazy(() => import('modal/modalViewImage' /* webpackChunkName: "modalViewImage" */)); -const ModalWalletDecrypt = React.lazy(() => - import('modal/modalWalletDecrypt' /* webpackChunkName: "modalWalletDecrypt" */) -); -const ModalWalletEncrypt = React.lazy(() => - import('modal/modalWalletEncrypt' /* webpackChunkName: "modalWalletEncrypt" */) -); -const ModalWalletUnlock = React.lazy(() => - import('modal/modalWalletUnlock' /* webpackChunkName: "modalWalletUnlock" */) -); -const ModalYoutubeWelcome = React.lazy(() => - import('modal/modalYoutubeWelcome' /* webpackChunkName: "modalYoutubeWelcome" */) -); +const ModalAffirmPurchase = lazyImport(() => import('modal/modalAffirmPurchase' /* webpackChunkName: "modalAffirmPurchase" */)); +const ModalAutoGenerateThumbnail = lazyImport(() => import('modal/modalAutoGenerateThumbnail' /* webpackChunkName: "modalAutoGenerateThumbnail" */)); +const ModalAutoUpdateDownloaded = lazyImport(() => import('modal/modalAutoUpdateDownloaded' /* webpackChunkName: "modalAutoUpdateDownloaded" */)); +const ModalClaimCollectionAdd = lazyImport(() => import('modal/modalClaimCollectionAdd' /* webpackChunkName: "modalClaimCollectionAdd" */)); +const ModalCommentAcknowledgement = lazyImport(() => import('modal/modalCommentAcknowledgement' /* webpackChunkName: "modalCommentAcknowledgement" */)); +const ModalConfirmAge = lazyImport(() => import('modal/modalConfirmAge' /* webpackChunkName: "modalConfirmAge" */)); +const ModalConfirmThumbnailUpload = lazyImport(() => import('modal/modalConfirmThumbnailUpload' /* webpackChunkName: "modalConfirmThumbnailUpload" */)); +const ModalConfirmTransaction = lazyImport(() => import('modal/modalConfirmTransaction' /* webpackChunkName: "modalConfirmTransaction" */)); +const ModalDeleteCollection = lazyImport(() => import('modal/modalRemoveCollection' /* webpackChunkName: "modalRemoveCollection" */)); +const ModalDownloading = lazyImport(() => import('modal/modalDownloading' /* webpackChunkName: "modalDownloading" */)); +const ModalError = lazyImport(() => import('modal/modalError' /* webpackChunkName: "modalError" */)); +const ModalFileSelection = lazyImport(() => import('modal/modalFileSelection' /* webpackChunkName: "modalFileSelection" */)); +const ModalFileTimeout = lazyImport(() => import('modal/modalFileTimeout' /* webpackChunkName: "modalFileTimeout" */)); +const ModalFirstReward = lazyImport(() => import('modal/modalFirstReward' /* webpackChunkName: "modalFirstReward" */)); +const ModalFirstSubscription = lazyImport(() => import('modal/modalFirstSubscription' /* webpackChunkName: "modalFirstSubscription" */)); +const ModalImageUpload = lazyImport(() => import('modal/modalImageUpload' /* webpackChunkName: "modalImageUpload" */)); +const ModalMassTipsUnlock = lazyImport(() => import('modal/modalMassTipUnlock' /* webpackChunkName: "modalMassTipUnlock" */)); +const ModalMobileSearch = lazyImport(() => import('modal/modalMobileSearch' /* webpackChunkName: "modalMobileSearch" */)); +const ModalOpenExternalResource = lazyImport(() => import('modal/modalOpenExternalResource' /* webpackChunkName: "modalOpenExternalResource" */)); +const ModalPasswordUnsave = lazyImport(() => import('modal/modalPasswordUnsave' /* webpackChunkName: "modalPasswordUnsave" */)); +const ModalPhoneCollection = lazyImport(() => import('modal/modalPhoneCollection' /* webpackChunkName: "modalPhoneCollection" */)); +const ModalPublish = lazyImport(() => import('modal/modalPublish' /* webpackChunkName: "modalPublish" */)); +const ModalPublishPreview = lazyImport(() => import('modal/modalPublishPreview' /* webpackChunkName: "modalPublishPreview" */)); +const ModalRemoveBtcSwapAddress = lazyImport(() => import('modal/modalRemoveBtcSwapAddress' /* webpackChunkName: "modalRemoveBtcSwapAddress" */)); +const ModalRemoveFile = lazyImport(() => import('modal/modalRemoveFile' /* webpackChunkName: "modalRemoveFile" */)); +const ModalRevokeClaim = lazyImport(() => import('modal/modalRevokeClaim' /* webpackChunkName: "modalRevokeClaim" */)); +const ModalRewardCode = lazyImport(() => import('modal/modalRewardCode' /* webpackChunkName: "modalRewardCode" */)); +const ModalSendTip = lazyImport(() => import('modal/modalSendTip' /* webpackChunkName: "modalSendTip" */)); +const ModalSetReferrer = lazyImport(() => import('modal/modalSetReferrer' /* webpackChunkName: "modalSetReferrer" */)); +const ModalSignOut = lazyImport(() => import('modal/modalSignOut' /* webpackChunkName: "modalSignOut" */)); +const ModalSocialShare = lazyImport(() => import('modal/modalSocialShare' /* webpackChunkName: "modalSocialShare" */)); +const ModalSupportsLiquidate = lazyImport(() => import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */)); +const ModalSyncEnable = lazyImport(() => import('modal/modalSyncEnable' /* webpackChunkName: "modalSyncEnable" */)); +const ModalTransactionFailed = lazyImport(() => import('modal/modalTransactionFailed' /* webpackChunkName: "modalTransactionFailed" */)); +const ModalUpgrade = lazyImport(() => import('modal/modalUpgrade' /* webpackChunkName: "modalUpgrade" */)); +const ModalViewImage = lazyImport(() => import('modal/modalViewImage' /* webpackChunkName: "modalViewImage" */)); +const ModalWalletDecrypt = lazyImport(() => import('modal/modalWalletDecrypt' /* webpackChunkName: "modalWalletDecrypt" */)); +const ModalWalletEncrypt = lazyImport(() => import('modal/modalWalletEncrypt' /* webpackChunkName: "modalWalletEncrypt" */)); +const ModalWalletUnlock = lazyImport(() => import('modal/modalWalletUnlock' /* webpackChunkName: "modalWalletUnlock" */)); +const ModalYoutubeWelcome = lazyImport(() => import('modal/modalYoutubeWelcome' /* webpackChunkName: "modalYoutubeWelcome" */)); type Props = { modal: { id: string, modalProps: {} }, diff --git a/ui/page/file/view.jsx b/ui/page/file/view.jsx index d671b6972..1bd170cbf 100644 --- a/ui/page/file/view.jsx +++ b/ui/page/file/view.jsx @@ -1,6 +1,7 @@ // @flow import * as React from 'react'; import classnames from 'classnames'; +import { lazyImport } from 'util/lazyImport'; import Page from 'component/page'; import * as RENDER_MODES from 'constants/file_render_modes'; import FileTitleSection from 'component/fileTitleSection'; @@ -12,7 +13,7 @@ import CollectionContent from 'component/collectionContentSidebar'; import CommentsList from 'component/commentsList'; import Empty from 'component/common/empty'; -const PostViewer = React.lazy(() => import('component/postViewer' /* webpackChunkName: "postViewer" */)); +const PostViewer = lazyImport(() => import('component/postViewer' /* webpackChunkName: "postViewer" */)); export const PRIMARY_PLAYER_WRAPPER_CLASS = 'file-page__video-container'; diff --git a/ui/page/show/view.jsx b/ui/page/show/view.jsx index f4ef4e6f1..a1b807496 100644 --- a/ui/page/show/view.jsx +++ b/ui/page/show/view.jsx @@ -2,6 +2,7 @@ import { DOMAIN } from 'config'; import * as PAGES from 'constants/pages'; import React, { useEffect } from 'react'; +import { lazyImport } from 'util/lazyImport'; import { Redirect, useHistory } from 'react-router-dom'; import Spinner from 'component/spinner'; import ChannelPage from 'page/channel'; @@ -11,12 +12,10 @@ import Card from 'component/common/card'; import { formatLbryUrlForWeb } from 'util/url'; import { parseURI, COLLECTIONS_CONSTS } from 'lbry-redux'; -const AbandonedChannelPreview = React.lazy(() => - import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */) -); -const FilePage = React.lazy(() => import('page/file' /* webpackChunkName: "filePage" */)); -const LivestreamPage = React.lazy(() => import('page/livestream' /* webpackChunkName: "livestream" */)); -const Yrbl = React.lazy(() => import('component/yrbl' /* webpackChunkName: "yrbl" */)); +const AbandonedChannelPreview = lazyImport(() => import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)); +const FilePage = lazyImport(() => import('page/file' /* webpackChunkName: "filePage" */)); +const LivestreamPage = lazyImport(() => import('page/livestream' /* webpackChunkName: "livestream" */)); +const Yrbl = lazyImport(() => import('component/yrbl' /* webpackChunkName: "yrbl" */)); type Props = { isResolvingUri: boolean, diff --git a/ui/util/lazyImport.js b/ui/util/lazyImport.js new file mode 100644 index 000000000..d5f05f60a --- /dev/null +++ b/ui/util/lazyImport.js @@ -0,0 +1,23 @@ +import React from 'react'; + +export const lazyImport = (componentImport) => + React.lazy(async () => { + const pageHasAlreadyBeenForceRefreshed = JSON.parse( + window.localStorage.getItem('page-has-been-force-refreshed') || 'false' + ); + + try { + const component = await componentImport(); + window.localStorage.setItem('page-has-been-force-refreshed', 'false'); + return component; + } catch (error) { + if (!pageHasAlreadyBeenForceRefreshed) { + // It's highly likely that the user's session is old. Try reloading once. + window.localStorage.setItem('page-has-been-force-refreshed', 'true'); + return window.location.reload(); + } + + // If it still didn't work, then relay the error. + throw error; + } + }); -- 2.45.2