From cffadaebdf383f917bd8fe94477ae15bd38c7cae Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 21 Oct 2022 12:01:59 -0700 Subject: [PATCH] rsc react externals --- package.json | 1 + packages/next/build/webpack-config.ts | 9 ++++++- pnpm-lock.yaml | 16 +++++++++++- test/e2e/app-dir/rsc-external.test.ts | 25 +++++++++++-------- .../app/external-imports/client/page.js | 8 ++++-- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index ee7fcf8a55073..9b126d24ddcf4 100644 --- a/package.json +++ b/package.json @@ -195,6 +195,7 @@ "shell-quote": "1.7.3", "styled-components": "5.3.3", "styled-jsx-plugin-postcss": "3.0.2", + "swr": "2.0.0-rc.0", "tailwindcss": "1.1.3", "taskr": "1.1.0", "tree-kill": "1.2.2", diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index b3a309077bb0a..b43ff2363c316 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -447,6 +447,7 @@ export async function resolveExternal( resolveRequest: string ) => Promise<[string | null, boolean]>, isLocalCallback?: (res: string) => any, + layer: string | null = null, baseResolveCheck = true, esmResolveOptions: any = NODE_ESM_RESOLVE_OPTIONS, nodeResolveOptions: any = NODE_RESOLVE_OPTIONS, @@ -461,6 +462,11 @@ export async function resolveExternal( let preferEsmOptions = esmExternals && isEsmRequested ? [true, false] : [false] + + // TODO-APP: temporarily disabled esm resolving for appDir until + // react, react-dom are properly bundled for SSR client layer + if (appDir && layer == null) preferEsmOptions = [false] + for (const preferEsm of preferEsmOptions) { const resolve = getResolve( preferEsm ? esmResolveOptions : nodeResolveOptions @@ -1121,7 +1127,8 @@ export default async function getBaseWebpackConfig( request, isEsmRequested, getResolve, - isLocal ? isLocalCallback : undefined + isLocal ? isLocalCallback : undefined, + layer ) if ('localRes' in resolveResult) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36240fedaebc3..1ad98c8c3c8b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -158,6 +158,7 @@ importers: shell-quote: 1.7.3 styled-components: 5.3.3 styled-jsx-plugin-postcss: 3.0.2 + swr: 2.0.0-rc.0 tailwindcss: 1.1.3 taskr: 1.1.0 tree-kill: 1.2.2 @@ -315,6 +316,7 @@ importers: shell-quote: 1.7.3 styled-components: 5.3.3_vtcxgy2wlmese7djxl6h7ok674 styled-jsx-plugin-postcss: 3.0.2 + swr: 2.0.0-rc.0_react@18.2.0 tailwindcss: 1.1.3 taskr: 1.1.0 tree-kill: 1.2.2 @@ -28290,6 +28292,19 @@ packages: upper-case: 1.1.3 dev: true + /swr/2.0.0-rc.0_react@18.2.0: + resolution: + { + integrity: sha512-QOp+4Cqnb/uuLKeuRDh7aT+ws6wSWWKPqfyIpBXK8DM3IugOYeLO5v+390I0p1MIfRd0CQlAIJZBEgmHaTfDuA==, + } + engines: { pnpm: '7' } + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0_react@18.2.0 + dev: true + /symbol-observable/1.0.1: resolution: { @@ -29946,7 +29961,6 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: react: 18.2.0 - dev: false /use/3.1.1: resolution: diff --git a/test/e2e/app-dir/rsc-external.test.ts b/test/e2e/app-dir/rsc-external.test.ts index c7c030d6f37e0..89331aef400b9 100644 --- a/test/e2e/app-dir/rsc-external.test.ts +++ b/test/e2e/app-dir/rsc-external.test.ts @@ -2,6 +2,7 @@ import path from 'path' import { renderViaHTTP, fetchViaHTTP } from 'next-test-utils' import { createNext, FileRef } from 'e2e-utils' import { NextInstance } from 'test/lib/next-modes/base' +import webdriver from 'next-webdriver' async function resolveStreamResponse(response: any, onData?: any) { let result = '' @@ -31,6 +32,7 @@ describe('app dir - rsc external dependency', () => { dependencies: { react: 'latest', 'react-dom': 'latest', + swr: '2.0.0-rc.0', }, packageJson: { scripts: { @@ -71,17 +73,20 @@ describe('app dir - rsc external dependency', () => { const serverHtml = await renderViaHTTP(next.url, '/external-imports/server') const sharedHtml = await renderViaHTTP(next.url, '/shared-esm-dep') - expect(clientHtml).toContain('module type:esm-export') - expect(clientHtml).toContain('export named:named') - expect(clientHtml).toContain('export value:123') - expect(clientHtml).toContain('export array:4,5,6') - expect(clientHtml).toContain('export object:{x:1}') + const browser = await webdriver(next.url, '/external-imports/client') + const browserClientText = await browser.elementByCss('#content').text() - // support esm module imports on server side, and indirect imports from shared components - expect(serverHtml).toContain('random-module-instance') - expect(sharedHtml).toContain( - 'node_modules instance from client module random-module-instance' - ) + function containClientContent(content) { + expect(content).toContain('module type:esm-export') + expect(content).toContain('export named:named') + expect(content).toContain('export value:123') + expect(content).toContain('export array:4,5,6') + expect(content).toContain('export object:{x:1}') + expect(content).toContain('swr-state') + } + + containClientContent(clientHtml) + containClientContent(browserClientText) }) it('should transpile specific external packages with the `transpilePackages` option', async () => { diff --git a/test/e2e/app-dir/rsc-external/app/external-imports/client/page.js b/test/e2e/app-dir/rsc-external/app/external-imports/client/page.js index 4c4c3499882ce..c655eccfaee7c 100644 --- a/test/e2e/app-dir/rsc-external/app/external-imports/client/page.js +++ b/test/e2e/app-dir/rsc-external/app/external-imports/client/page.js @@ -1,18 +1,22 @@ 'use client' import getType, { named, value, array, obj } from 'non-isomorphic-text' - import add from 'untranspiled-module' +// ESM externals has react has a peer dependency +import useSWR from 'swr' + export default function Page() { + const { data } = useSWR('swr-state', (v) => v, { fallbackData: 'swr-state' }) return ( -
+
{`module type:${getType()}`}
{`export named:${named}`}
{`export value:${value}`}
{`export array:${array.join(',')}`}
{`export object:{x:${obj.x}}`}
{`transpilePackages:${add(2, 3)}`}
+
{data}
) }