diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index 5a0464a09..d463b983b 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -11,9 +11,6 @@ import { import path from 'node:path' import os from 'node:os' -// TODO: parallel? -// TODO: all tests don't need to be tested in all variants? - test.describe('dev-default', () => { const f = useFixture({ root: 'examples/basic', mode: 'dev' }) defineTest(f) @@ -824,6 +821,14 @@ function defineTest(f: Fixture) { ) }) + test('transitive cjs dep', async ({ page }) => { + await page.goto(f.url()) + await waitForHydration(page) + await expect(page.getByTestId('transitive-cjs-client')).toHaveText( + 'ok:browser', + ) + }) + test('use cache function', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) diff --git a/packages/plugin-rsc/examples/basic/package.json b/packages/plugin-rsc/examples/basic/package.json index 43d95645d..6fb6344bc 100644 --- a/packages/plugin-rsc/examples/basic/package.json +++ b/packages/plugin-rsc/examples/basic/package.json @@ -21,6 +21,7 @@ "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "latest", + "@vitejs/test-dep-transitive-cjs": "file:./test-dep/transitive-cjs", "@vitejs/test-dep-client-in-server": "file:./test-dep/client-in-server", "@vitejs/test-dep-client-in-server2": "file:./test-dep/client-in-server2", "@vitejs/test-dep-server-in-client": "file:./test-dep/server-in-client", diff --git a/packages/plugin-rsc/examples/basic/src/routes/deps/transitive-cjs/client.tsx b/packages/plugin-rsc/examples/basic/src/routes/deps/transitive-cjs/client.tsx new file mode 100644 index 000000000..11045ee39 --- /dev/null +++ b/packages/plugin-rsc/examples/basic/src/routes/deps/transitive-cjs/client.tsx @@ -0,0 +1,12 @@ +'use client' + +// @ts-ignore +import { TestClient } from '@vitejs/test-dep-transitive-cjs/client' + +export function TestTransitiveCjsClient() { + return ( +
+ [test-dep-transitive-cjs-client: ] +
+ ) +} diff --git a/packages/plugin-rsc/examples/basic/src/routes/root.tsx b/packages/plugin-rsc/examples/basic/src/routes/root.tsx index 52ce38dee..f679c362e 100644 --- a/packages/plugin-rsc/examples/basic/src/routes/root.tsx +++ b/packages/plugin-rsc/examples/basic/src/routes/root.tsx @@ -29,6 +29,7 @@ import { TestTemporaryReference } from './temporary-reference/client' import { TestUseCache } from './use-cache/server' import { TestHydrationMismatch } from './hydration-mismatch/server' import { TestBrowserOnly } from './browser-only/client' +import { TestTransitiveCjsClient } from './deps/transitive-cjs/client' export function Root(props: { url: URL }) { return ( @@ -67,6 +68,7 @@ export function Root(props: { url: URL }) { + diff --git a/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/client.js b/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/client.js new file mode 100644 index 000000000..db2fd4b6f --- /dev/null +++ b/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/client.js @@ -0,0 +1,27 @@ +'use client' + +import React from 'react' + +// similar to swr +// https://github.com/vercel/swr/blob/063fe55dddb95f0b6c3f1637a935c43d732ded78/src/index/use-swr.ts#L3 +import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' + +const h = React.createElement + +const noopStore = () => () => {} + +export function TestClient() { + const value = useSyncExternalStore( + noopStore, + () => 'ok:browser', + () => 'ok:ssr', + ) + + return h( + 'span', + { + 'data-testid': 'transitive-cjs-client', + }, + value, + ) +} diff --git a/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/package.json b/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/package.json new file mode 100644 index 000000000..8368742da --- /dev/null +++ b/packages/plugin-rsc/examples/basic/test-dep/transitive-cjs/package.json @@ -0,0 +1,14 @@ +{ + "name": "@vitejs/test-dep-transitive-cjs", + "private": true, + "type": "module", + "exports": { + "./client": "./client.js" + }, + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "react": "*" + } +} diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index 97d0f30b8..b0eec5511 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -135,12 +135,29 @@ export default { fetch: handler }; minify: false, manifest: true, }, - optimizeDeps: { - exclude: [ - '@vitejs/test-dep-client-in-server/client', - '@vitejs/test-dep-client-in-server2/client', - '@vitejs/test-dep-server-in-client/client', - ], + environments: { + client: { + optimizeDeps: { + entries: [ + './src/routes/**/client.tsx', + './src/framework/entry.browser.tsx', + ], + exclude: [ + '@vitejs/test-dep-client-in-server/client', + '@vitejs/test-dep-client-in-server2/client', + '@vitejs/test-dep-server-in-client/client', + ], + }, + }, + ssr: { + optimizeDeps: { + // TODO: this should be somehow auto inferred or at least show a warning + // to guide users to `optimizeDeps.include` + include: [ + '@vitejs/test-dep-transitive-cjs > use-sync-external-store/shim/index.js', + ], + }, + }, }, }) as any diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8bd988406..8b1fa0154 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -542,6 +542,9 @@ importers: '@vitejs/test-dep-server-in-server': specifier: file:./test-dep/server-in-server version: file:packages/plugin-rsc/examples/basic/test-dep/server-in-server(react@19.1.0) + '@vitejs/test-dep-transitive-cjs': + specifier: file:./test-dep/transitive-cjs + version: file:packages/plugin-rsc/examples/basic/test-dep/transitive-cjs(react@19.1.0) rsc-html-stream: specifier: ^0.0.7 version: 0.0.7 @@ -3094,6 +3097,11 @@ packages: peerDependencies: react: '*' + '@vitejs/test-dep-transitive-cjs@file:packages/plugin-rsc/examples/basic/test-dep/transitive-cjs': + resolution: {directory: packages/plugin-rsc/examples/basic/test-dep/transitive-cjs, type: directory} + peerDependencies: + react: '*' + '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} @@ -5536,6 +5544,11 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -7656,6 +7669,11 @@ snapshots: dependencies: react: 19.1.0 + '@vitejs/test-dep-transitive-cjs@file:packages/plugin-rsc/examples/basic/test-dep/transitive-cjs(react@19.1.0)': + dependencies: + react: 19.1.0 + use-sync-external-store: 1.5.0(react@19.1.0) + '@vitest/expect@3.2.4': dependencies: '@types/chai': 5.2.2 @@ -10440,6 +10458,10 @@ snapshots: dependencies: punycode: 2.3.1 + use-sync-external-store@1.5.0(react@19.1.0): + dependencies: + react: 19.1.0 + util-deprecate@1.0.2: {} valibot@0.41.0(typescript@5.8.3):