From 7a520a6a4aca6ea4304ed8d85779605c7ec2ebbf Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 12 Jan 2023 10:29:13 +0100 Subject: [PATCH 1/3] dynamic dynamic refactor --- .../{dynamic-no-ssr.ts => dynamic-no-ssr.tsx} | 2 +- packages/next/src/shared/lib/dynamic.tsx | 48 ++++--------------- packages/next/src/shared/lib/loadable.d.ts | 15 ------ .../shared/lib/{loadable.ts => loadable.tsx} | 29 ++++++----- 4 files changed, 27 insertions(+), 67 deletions(-) rename packages/next/src/shared/lib/{dynamic-no-ssr.ts => dynamic-no-ssr.tsx} (83%) delete mode 100644 packages/next/src/shared/lib/loadable.d.ts rename packages/next/src/shared/lib/{loadable.ts => loadable.tsx} (93%) diff --git a/packages/next/src/shared/lib/dynamic-no-ssr.ts b/packages/next/src/shared/lib/dynamic-no-ssr.tsx similarity index 83% rename from packages/next/src/shared/lib/dynamic-no-ssr.ts rename to packages/next/src/shared/lib/dynamic-no-ssr.tsx index d32e49b51639..e5c1c1e22b2c 100644 --- a/packages/next/src/shared/lib/dynamic-no-ssr.ts +++ b/packages/next/src/shared/lib/dynamic-no-ssr.tsx @@ -11,7 +11,7 @@ export function suspense() { type Child = React.ReactElement -export default function NoSSR({ children }: { children: Child }): Child { +export function NoSSR({ children }: { children: Child }): Child { if (typeof window === 'undefined') { suspense() } diff --git a/packages/next/src/shared/lib/dynamic.tsx b/packages/next/src/shared/lib/dynamic.tsx index 042438119d39..cd12962f493c 100644 --- a/packages/next/src/shared/lib/dynamic.tsx +++ b/packages/next/src/shared/lib/dynamic.tsx @@ -1,6 +1,5 @@ -import React, { lazy, Suspense } from 'react' +import React from 'react' import Loadable from './loadable' -import NoSSR from './dynamic-no-ssr' type ComponentModule

= { default: React.ComponentType

} @@ -8,10 +7,6 @@ export declare type LoaderComponent

= Promise< React.ComponentType

| ComponentModule

> -type NormalizedLoader

= () => Promise<{ - default: React.ComponentType

-}> - export declare type Loader

= | (() => LoaderComponent

) | LoaderComponent

@@ -57,30 +52,6 @@ export type LoadableFn

= ( export type LoadableComponent

= React.ComponentType

-export function noSSR

( - LoadableInitializer: NormalizedLoader

, - loadableOptions: DynamicOptions

-): React.ComponentType

{ - // Removing webpack and modules means react-loadable won't try preloading - delete loadableOptions.webpack - delete loadableOptions.modules - - const NoSSRComponent = lazy(LoadableInitializer) - - const Loading = loadableOptions.loading! - const fallback = ( - - ) - - return (props: any) => ( - - - - - - ) -} - export default function dynamic

( dynamicOptions: DynamicOptions

| Loader

, options?: DynamicOptions

@@ -127,26 +98,25 @@ export default function dynamic

( loadableOptions = { ...loadableOptions, ...options } const loaderFn = loadableOptions.loader as () => LoaderComponent

- const loader = () => loaderFn().then(convertModule) + const loader = () => + loaderFn != null + ? loaderFn().then(convertModule) + : Promise.resolve(convertModule(() => null)) // coming from build/babel/plugins/react-loadable-plugin.js if (loadableOptions.loadableGenerated) { loadableOptions = { ...loadableOptions, ...loadableOptions.loadableGenerated, - loader, } delete loadableOptions.loadableGenerated } // support for disabling server side rendering, eg: dynamic(() => import('../hello-world'), {ssr: false}). - if (typeof loadableOptions.ssr === 'boolean') { - if (!loadableOptions.ssr) { - delete loadableOptions.ssr - return noSSR(loader, loadableOptions) - } - delete loadableOptions.ssr + if (typeof loadableOptions.ssr === 'boolean' && !loadableOptions.ssr) { + delete loadableOptions.webpack + delete loadableOptions.modules } - return loadableFn(loadableOptions) + return loadableFn({ ...loadableOptions, loader: loader as Loader

}) } diff --git a/packages/next/src/shared/lib/loadable.d.ts b/packages/next/src/shared/lib/loadable.d.ts deleted file mode 100644 index 8ac6e8043379..000000000000 --- a/packages/next/src/shared/lib/loadable.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* tslint:disable */ -import React from 'react' - -declare namespace LoadableExport { - interface ILoadable { -

(opts: any): React.ComponentClass

- Map

(opts: any): React.ComponentType

- preloadAll(): Promise - } -} - -// eslint-disable-next-line @typescript-eslint/no-redeclare -declare const LoadableExport: LoadableExport.ILoadable - -export = LoadableExport diff --git a/packages/next/src/shared/lib/loadable.ts b/packages/next/src/shared/lib/loadable.tsx similarity index 93% rename from packages/next/src/shared/lib/loadable.ts rename to packages/next/src/shared/lib/loadable.tsx index 3d075c1957f3..5f49d65e4987 100644 --- a/packages/next/src/shared/lib/loadable.ts +++ b/packages/next/src/shared/lib/loadable.tsx @@ -23,6 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE // Modified to be compatible with webpack 4 / Next.js import React from 'react' +import { NoSSR } from './dynamic-no-ssr' import { LoadableContext } from './loadable-context' const ALL_INITIALIZERS: any[] = [] @@ -62,6 +63,7 @@ function createLoadableComponent(loadFn: any, options: any) { timeout: null, webpack: null, modules: null, + ssr: true, }, options ) @@ -117,25 +119,28 @@ function createLoadableComponent(loadFn: any, options: any) { }) } } + function LoadableComponent(props: any) { useLoadableModule() - const fallbackElement = React.createElement(opts.loading, { - isLoading: true, - pastDelay: true, - error: null, - }) + const Loading = opts.loading + const fallbackElement = ( + + ) + + const Wrap = opts.ssr ? React.Fragment : NoSSR + const Lazy = opts.lazy - return React.createElement( - React.Suspense, - { - fallback: fallbackElement, - }, - React.createElement(opts.lazy, props) + return ( + + + + + ) } - LoadableComponent.preload = () => init() + LoadableComponent.preload = () => opts.ssr && init() LoadableComponent.displayName = 'LoadableComponent' return LoadableComponent From 507e9693521634592db3e2b325a65c1b489316a3 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 12 Jan 2023 22:24:35 +0100 Subject: [PATCH 2/3] update test --- packages/next/src/shared/lib/loadable.tsx | 2 +- test/unit/next-dynamic.test.tsx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/next/src/shared/lib/loadable.tsx b/packages/next/src/shared/lib/loadable.tsx index 5f49d65e4987..d4758716cc17 100644 --- a/packages/next/src/shared/lib/loadable.tsx +++ b/packages/next/src/shared/lib/loadable.tsx @@ -140,7 +140,7 @@ function createLoadableComponent(loadFn: any, options: any) { ) } - LoadableComponent.preload = () => opts.ssr && init() + LoadableComponent.preload = () => init() LoadableComponent.displayName = 'LoadableComponent' return LoadableComponent diff --git a/test/unit/next-dynamic.test.tsx b/test/unit/next-dynamic.test.tsx index e78e15d6ff0e..c11791eb35dc 100644 --- a/test/unit/next-dynamic.test.tsx +++ b/test/unit/next-dynamic.test.tsx @@ -8,6 +8,9 @@ import dynamic from 'next/dynamic' describe('next/dynamic', () => { it('test dynamic with jest', () => { const App = dynamic(() => import('./fixtures/stub-components/hello')) + + expect(App.preload).toBeDefined() + act(() => { const { unmount } = render() unmount() From 1df4ff0e5f617da2ba3be3dea05bb5b9586a05f6 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 12 Jan 2023 22:33:39 +0100 Subject: [PATCH 3/3] ts ignore in test --- test/unit/next-dynamic.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/next-dynamic.test.tsx b/test/unit/next-dynamic.test.tsx index c11791eb35dc..2e1c7cdea09d 100644 --- a/test/unit/next-dynamic.test.tsx +++ b/test/unit/next-dynamic.test.tsx @@ -9,6 +9,7 @@ describe('next/dynamic', () => { it('test dynamic with jest', () => { const App = dynamic(() => import('./fixtures/stub-components/hello')) + // @ts-ignore expect(App.preload).toBeDefined() act(() => {