diff --git a/packages/next/build/entries.ts b/packages/next/build/entries.ts index 2213d83bce63..524027a148bb 100644 --- a/packages/next/build/entries.ts +++ b/packages/next/build/entries.ts @@ -313,7 +313,10 @@ export function getViewsEntry(opts: { viewsDir: string pageExtensions: string[] }) { - return `next-view-loader?${stringify(opts)}!` + return { + import: `next-view-loader?${stringify(opts)}!`, + layer: 'sc_server', + } } export function getServerlessEntry(opts: { diff --git a/packages/next/build/webpack/loaders/next-view-loader.ts b/packages/next/build/webpack/loaders/next-view-loader.ts index d0c1370a2901..481b35b2bc37 100644 --- a/packages/next/build/webpack/loaders/next-view-loader.ts +++ b/packages/next/build/webpack/loaders/next-view-loader.ts @@ -119,6 +119,8 @@ const nextViewLoader: webpack.LoaderDefinitionFunction<{ export const components = { ${componentsCode.join(',\n')} }; + + export const __next_view_webpack_require__ = __webpack_require__ ` return result } diff --git a/packages/next/server/load-components.ts b/packages/next/server/load-components.ts index fea6d8ffe300..67a31e5ef140 100644 --- a/packages/next/server/load-components.ts +++ b/packages/next/server/load-components.ts @@ -137,7 +137,8 @@ export async function loadComponents( await requirePage( normalizePagePath(pathname) + '.__sc_client__', distDir, - serverless + serverless, + rootEnabled ) } catch (_) { // This page might not be a server component page, so there is no __sc_client__ diff --git a/packages/next/server/view-render.tsx b/packages/next/server/view-render.tsx index 8fbdaafdec75..a4f6c3d840b0 100644 --- a/packages/next/server/view-render.tsx +++ b/packages/next/server/view-render.tsx @@ -165,10 +165,11 @@ function createServerComponentRenderer( ) { // We need to expose the `__webpack_require__` API globally for // react-server-dom-webpack. This is a hack until we find a better way. - if (ComponentMod.__next_rsc__) { + if (ComponentMod.__next_view_webpack_require__ || ComponentMod.__next_rsc__) { // @ts-ignore - globalThis.__webpack_require__ = - ComponentMod.__next_rsc__.__webpack_require__ + globalThis.__webpack_require__ = ComponentMod.__next_view_webpack_require__ + ? ComponentMod.__next_view_webpack_require__ + : ComponentMod.__next_rsc__.__webpack_require__ // @ts-ignore globalThis.__webpack_chunk_load__ = () => Promise.resolve() diff --git a/test/e2e/views-dir/index.test.ts b/test/e2e/views-dir/index.test.ts index b1d1c052af59..91382a622bce 100644 --- a/test/e2e/views-dir/index.test.ts +++ b/test/e2e/views-dir/index.test.ts @@ -226,37 +226,47 @@ describe('views dir', () => { expect(html).toContain('hello from root/shared-component-route') }) - // TODO: implement - it.skip('should serve client component', async () => { - const html = await renderViaHTTP(next.url, '/client-component-route') - expect(html).toContain('hello from root/client-component-route. count: 0') - - const browser = await webdriver(next.url, '/client-component-route') - // After hydration count should be 1 - expect(await browser.elementByCss('p').text()).toBe( - 'hello from root/client-component-route. count: 1' - ) + describe('should serve client component', () => { + it('should serve server-side', async () => { + const html = await renderViaHTTP(next.url, '/client-component-route') + const $ = cheerio.load(html) + expect($('p').text()).toBe( + 'hello from root/client-component-route. count: 0' + ) + }) + + // TODO: Implement hydration + it.skip('should serve client-side', async () => { + const browser = await webdriver(next.url, '/client-component-route') + // After hydration count should be 1 + expect(await browser.elementByCss('p').text()).toBe( + 'hello from root/client-component-route. count: 1' + ) + }) }) - // TODO: implement - it.skip('should include client component layout with server component route', async () => { - const html = await renderViaHTTP(next.url, '/client-nested') - const $ = cheerio.load(html) - // Should not be nested in dashboard - expect($('h1').text()).toBe('Client Nested. Count: 0') - // Should include the page text - expect($('p').text()).toBe('hello from root/client-nested') - - const browser = await webdriver(next.url, '/client-nested') - // After hydration count should be 1 - expect(await browser.elementByCss('h1').text()).toBe( - 'Client Nested. Count: 0' - ) - - // After hydration count should be 1 - expect(await browser.elementByCss('h1').text()).toBe( - 'hello from root/client-nested' - ) + describe('should include client component layout with server component route', () => { + it('should include it server-side', async () => { + const html = await renderViaHTTP(next.url, '/client-nested') + const $ = cheerio.load(html) + // Should not be nested in dashboard + expect($('h1').text()).toBe('Client Nested. Count: 0') + // Should include the page text + expect($('p').text()).toBe('hello from root/client-nested') + }) + + // TODO: Implement hydration + it.skip('should include it client-side', async () => { + const browser = await webdriver(next.url, '/client-nested') + // After hydration count should be 1 + expect(await browser.elementByCss('h1').text()).toBe( + 'Client Nested. Count: 0' + ) + // After hydration count should be 1 + expect(await browser.elementByCss('h1').text()).toBe( + 'hello from root/client-nested' + ) + }) }) }) })