diff --git a/packages/next/client/components/shared/dynamic/index.tsx b/packages/next/client/components/shared/dynamic/index.tsx new file mode 100644 index 000000000000..f333b8fef6c2 --- /dev/null +++ b/packages/next/client/components/shared/dynamic/index.tsx @@ -0,0 +1,21 @@ +import React from 'react' + +export type LoaderComponent

= Promise<{ + default: React.ComponentType

+}> + +export type Loader

= () => LoaderComponent

+ +export type DynamicOptions

= { + loader?: Loader

+} + +export type LoadableComponent

= React.ComponentType

+ +export default function dynamic

( + loader: Loader

+): React.ComponentType

{ + const LazyLoadable = React.lazy(loader) + + return LazyLoadable +} diff --git a/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.client.js b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.client.js new file mode 100644 index 000000000000..8b487da2a4eb --- /dev/null +++ b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.client.js @@ -0,0 +1,7 @@ +import dynamic from 'next/dist/client/components/shared/dynamic' + +const Dynamic = dynamic(() => import('../text-dynamic.client')) + +export function NextDynamicClientComponent() { + return +} diff --git a/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.server.js b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.server.js new file mode 100644 index 000000000000..18ac428cfc37 --- /dev/null +++ b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/dynamic.server.js @@ -0,0 +1,7 @@ +import dynamic from 'next/dist/client/components/shared/dynamic' + +const Dynamic = dynamic(() => import('../text-dynamic.server')) + +export function NextDynamicServerComponent() { + return +} diff --git a/test/e2e/app-dir/app/app/dashboard/index/react-lazy.client.js b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/react-lazy.client.js similarity index 59% rename from test/e2e/app-dir/app/app/dashboard/index/react-lazy.client.js rename to test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/react-lazy.client.js index 7188966f4c8e..0b1870fdeaf9 100644 --- a/test/e2e/app-dir/app/app/dashboard/index/react-lazy.client.js +++ b/test/e2e/app-dir/app/app/dashboard/index/dynamic-imports/react-lazy.client.js @@ -1,13 +1,13 @@ import { useState, lazy } from 'react' -const Lazy = lazy(() => import('./lazy.client.js')) +const Lazy = lazy(() => import('../text-lazy.client.js')) export function LazyClientComponent() { let [state] = useState('client') return ( <> -

hello from modern the {state}

+

hello from {state}

) } diff --git a/test/e2e/app-dir/app/app/dashboard/index/dynamic.client.js b/test/e2e/app-dir/app/app/dashboard/index/dynamic.client.js deleted file mode 100644 index a754ecb2082a..000000000000 --- a/test/e2e/app-dir/app/app/dashboard/index/dynamic.client.js +++ /dev/null @@ -1,11 +0,0 @@ -import { useState } from 'react' -import styles from './dynamic.module.css' - -export default function Dynamic() { - let [state] = useState('next dynamic') - return ( -

- hello from modern the {state} -

- ) -} diff --git a/test/e2e/app-dir/app/app/dashboard/index/next-dynamic.client.js b/test/e2e/app-dir/app/app/dashboard/index/next-dynamic.client.js deleted file mode 100644 index 6728a87f463c..000000000000 --- a/test/e2e/app-dir/app/app/dashboard/index/next-dynamic.client.js +++ /dev/null @@ -1,7 +0,0 @@ -import dynamic from 'next/dynamic' - -const Dynamic = dynamic(() => import('./dynamic.client')) - -export function NextDynamicClientComponent() { - return -} diff --git a/test/e2e/app-dir/app/app/dashboard/index/page.server.js b/test/e2e/app-dir/app/app/dashboard/index/page.server.js index d12da1104893..6dca33b19e80 100644 --- a/test/e2e/app-dir/app/app/dashboard/index/page.server.js +++ b/test/e2e/app-dir/app/app/dashboard/index/page.server.js @@ -1,10 +1,12 @@ -import { LazyClientComponent } from './react-lazy.client' -import { NextDynamicClientComponent } from './next-dynamic.client' +import { LazyClientComponent } from './dynamic-imports/react-lazy.client' +import { NextDynamicServerComponent } from './dynamic-imports/dynamic.server' +import { NextDynamicClientComponent } from './dynamic-imports/dynamic.client' export default function DashboardIndexPage() { return ( <>

hello from app/dashboard/index

+ diff --git a/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.client.js b/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.client.js new file mode 100644 index 000000000000..660b8c5953c6 --- /dev/null +++ b/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.client.js @@ -0,0 +1,11 @@ +import { useState } from 'react' +import styles from './dynamic.module.css' + +export default function Dynamic() { + let [state] = useState('dynamic on client') + return ( +

+ {`hello from ${state}`} +

+ ) +} diff --git a/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.server.js b/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.server.js new file mode 100644 index 000000000000..9f87f73b47df --- /dev/null +++ b/test/e2e/app-dir/app/app/dashboard/index/text-dynamic.server.js @@ -0,0 +1,9 @@ +import styles from './dynamic.module.css' + +export default function Dynamic() { + return ( +

+ hello from dynamic on server +

+ ) +} diff --git a/test/e2e/app-dir/app/app/dashboard/index/lazy.client.js b/test/e2e/app-dir/app/app/dashboard/index/text-lazy.client.js similarity index 100% rename from test/e2e/app-dir/app/app/dashboard/index/lazy.client.js rename to test/e2e/app-dir/app/app/dashboard/index/text-lazy.client.js diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 3541809f8150..9fe5df5af35a 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -67,8 +67,11 @@ describe('app dir', () => { it('should serve /index as separate page', async () => { const html = await renderViaHTTP(next.url, '/dashboard/index') expect(html).toContain('hello from app/dashboard/index') - // should load chunks generated via async import correctly + // should load chunks generated via async import correctly with React.lazy expect(html).toContain('hello from lazy') + // should support `dynamic` in both server and client components + expect(html).toContain('hello from dynamic on server') + expect(html).toContain('hello from dynamic on client') }) // TODO-APP: handle css modules fouc in dev @@ -77,7 +80,7 @@ describe('app dir', () => { expect( await browser.eval( - `window.getComputedStyle(document.querySelector('#css-text-dynamic')).color` + `window.getComputedStyle(document.querySelector('#css-text-dynamic-server')).color` ) ).toBe('rgb(0, 0, 255)') expect(