Skip to content

Commit c87dbc6

Browse files
committed
Merge branch '08-11-fix_rsc_remove_non-optimized_server_cjs_warning' into 08-11-refactor_rsc_remove_server_optimizedeps.include
2 parents fb86ae2 + 232cde2 commit c87dbc6

File tree

9 files changed

+103
-47
lines changed

9 files changed

+103
-47
lines changed

packages/plugin-rsc/e2e/basic.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,20 @@ test.describe('dev-non-optimized-cjs', () => {
5858
)
5959
})
6060

61-
const f = useFixture({ root: 'examples/basic', mode: 'dev' })
61+
const f = useFixture({
62+
root: 'examples/basic',
63+
mode: 'dev',
64+
cliOptions: {
65+
env: {
66+
DEBUG: 'vite-rsc:cjs',
67+
},
68+
},
69+
})
6270

6371
test('show warning', async ({ page }) => {
6472
await page.goto(f.url())
65-
expect(f.proc().stderr()).toContain(
66-
`Found non-optimized CJS dependency in 'ssr' environment.`,
73+
expect(f.proc().stderr()).toMatch(
74+
/non-optimized CJS dependency in 'ssr' environment.*@vitejs\/test-dep-cjs\/index.js/,
6775
)
6876
})
6977
})

packages/plugin-rsc/examples/react-router/cf/vite.config.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,6 @@ export default defineConfig({
3636
},
3737
],
3838
}),
39-
{
40-
name: 'no-server-optimize-deps',
41-
configEnvironment: {
42-
order: 'post',
43-
handler(name) {
44-
if (name === 'ssr' || name === 'rsc') {
45-
return {
46-
optimizeDeps: {
47-
noDiscovery: true,
48-
},
49-
}
50-
}
51-
},
52-
},
53-
},
5439
],
5540
environments: {
5641
client: {
@@ -60,14 +45,12 @@ export default defineConfig({
6045
},
6146
ssr: {
6247
optimizeDeps: {
63-
// include: ['react-router > cookie', 'react-router > set-cookie-parser'],
64-
// exclude: ['react-router'],
48+
exclude: ['react-router'],
6549
},
6650
},
6751
rsc: {
6852
optimizeDeps: {
69-
// include: ['react-router > cookie', 'react-router > set-cookie-parser'],
70-
// exclude: ['react-router'],
53+
exclude: ['react-router'],
7154
},
7255
},
7356
},

packages/plugin-rsc/src/plugin.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ import {
3232
} from './transforms'
3333
import { generateEncryptionKey, toBase64 } from './utils/encryption-utils'
3434
import { createRpcServer } from './utils/rpc'
35-
import { normalizeViteImportAnalysisUrl, prepareError } from './vite-utils'
35+
import {
36+
cleanUrl,
37+
normalizeViteImportAnalysisUrl,
38+
prepareError,
39+
} from './vite-utils'
3640
import { cjsModuleRunnerPlugin } from './plugins/cjs'
3741
import { evalValue, parseIdQuery } from './plugins/utils'
3842

@@ -959,9 +963,12 @@ function vitePluginUseClient(
959963
let importId: string
960964
let referenceKey: string
961965
const packageSource = packageSources.get(id)
962-
if (!packageSource && id.includes('?v=')) {
963-
assert(this.environment.mode === 'dev')
964-
// If non package source `?v=<hash>` reached here, this is a client boundary
966+
if (
967+
!packageSource &&
968+
this.environment.mode === 'dev' &&
969+
id.includes('/node_modules/')
970+
) {
971+
// If non package source reached here (often with ?v=... query), this is a client boundary
965972
// created by a package imported on server environment, which breaks the
966973
// expectation on dependency optimizer on browser. Directly copying over
967974
// "?v=<hash>" from client optimizer in client reference can make a hashed
@@ -978,9 +985,7 @@ function vitePluginUseClient(
978985
`[vite-rsc] detected an internal client boundary created by a package imported on rsc environment`,
979986
)
980987
}
981-
importId = `/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/${encodeURIComponent(
982-
id.split('?v=')[0]!,
983-
)}`
988+
importId = `/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/${encodeURIComponent(cleanUrl(id))}`
984989
referenceKey = importId
985990
} else if (packageSource) {
986991
if (this.environment.mode === 'dev') {
@@ -1223,8 +1228,10 @@ function vitePluginUseServer(
12231228
let normalizedId_: string | undefined
12241229
const getNormalizedId = () => {
12251230
if (!normalizedId_) {
1226-
if (id.includes('?v=')) {
1227-
assert(this.environment.mode === 'dev')
1231+
if (
1232+
this.environment.mode === 'dev' &&
1233+
id.includes('/node_modules/')
1234+
) {
12281235
const ignored =
12291236
useServerPluginOptions.ignoredPackageWarnings?.some(
12301237
(pattern) =>
@@ -1238,8 +1245,8 @@ function vitePluginUseServer(
12381245
)
12391246
}
12401247
// module runner has additional resolution step and it's not strict about
1241-
// module identity of `import(id)` like browser, so we simply strip it off.
1242-
id = id.split('?v=')[0]!
1248+
// module identity of `import(id)` like browser, so we simply strip queries such as `?v=`.
1249+
id = cleanUrl(id)
12431250
}
12441251
if (config.command === 'build') {
12451252
normalizedId_ = hashString(path.relative(config.root, id))

packages/plugin-rsc/src/plugins/cjs.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@ import path from 'node:path'
55
import fs from 'node:fs'
66
import * as esModuleLexer from 'es-module-lexer'
77
import { transformCjsToEsm } from '../transforms/cjs'
8+
import { createDebug } from '@hiogawa/utils'
9+
10+
const debug = createDebug('vite-rsc:cjs')
811

912
export function cjsModuleRunnerPlugin(): Plugin[] {
10-
// use-sync-external-store is known to work fine so don't show warning
11-
const warnedPackages = new Set<string>([
12-
'use-sync-external-store',
13-
'react',
14-
'react-dom',
15-
'@vitejs/plugin-rsc',
16-
])
13+
const warnedPackages = new Set<string>()
1714

1815
return [
1916
{
@@ -52,9 +49,8 @@ export function cjsModuleRunnerPlugin(): Plugin[] {
5249
// warning once per package
5350
const packageKey = extractPackageKey(id)
5451
if (!warnedPackages.has(packageKey)) {
55-
this.warn(
56-
`Found non-optimized CJS dependency in '${this.environment.name}' environment. ` +
57-
`It is recommended to add the dependency to 'environments.${this.environment.name}.optimizeDeps.include'.`,
52+
debug(
53+
`non-optimized CJS dependency in '${this.environment.name}' environment: ${id}`,
5854
)
5955
warnedPackages.add(packageKey)
6056
}
@@ -65,9 +61,10 @@ export function cjsModuleRunnerPlugin(): Plugin[] {
6561
// TODO: can we use cjs-module-lexer to properly define named exports?
6662
// for re-exports, we need to eagerly transform dependencies though.
6763
// https://github.com/nodejs/node/blob/f3adc11e37b8bfaaa026ea85c1cf22e3a0e29ae9/lib/internal/modules/esm/translators.js#L382-L409
68-
output.append(
69-
`\n;__vite_ssr_exportAll__(module.exports);\nexport default module.exports;\n`,
70-
)
64+
output.append(`
65+
;__vite_ssr_exportAll__(module.exports);
66+
export default module.exports;
67+
`)
7168
return {
7269
code: output.toString(),
7370
map: output.generateMap({ hires: 'boundary' }),

packages/plugin-rsc/src/plugins/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ export function parseIdQuery(id: string): {
1919
const query = Object.fromEntries(new URLSearchParams(rawQuery))
2020
return { filename, query }
2121
}
22+
23+
// https://github.com/vitejs/vite/blob/946831f986cb797009b8178659d2b31f570c44ff/packages/vite/src/shared/utils.ts#L31-L34
24+
const postfixRE = /[?#].*$/
25+
export function cleanUrl(url: string): string {
26+
return url.replace(postfixRE, '')
27+
}

packages/plugin-rsc/src/transforms/cjs.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { parseAstAsync } from 'vite'
1+
import { createServer, createServerModuleRunner, parseAstAsync } from 'vite'
22
import { describe, expect, it } from 'vitest'
33
import { debugSourceMap } from './test-utils'
44
import { transformCjsToEsm } from './cjs'
5+
import path from 'node:path'
56

67
describe(transformCjsToEsm, () => {
78
async function testTransform(input: string) {
@@ -83,4 +84,51 @@ if (true) {
8384
"
8485
`)
8586
})
87+
88+
it('e2e', async () => {
89+
const server = await createServer({
90+
configFile: false,
91+
logLevel: 'error',
92+
root: path.join(import.meta.dirname, 'fixtures/cjs'),
93+
plugins: [
94+
{
95+
name: 'cjs-module-runner-transform',
96+
async transform(code, id) {
97+
if (id.endsWith('.cjs')) {
98+
const ast = await parseAstAsync(code)
99+
const { output } = transformCjsToEsm(code, ast)
100+
output.append(`
101+
;__vite_ssr_exportAll__(module.exports);
102+
export default module.exports;
103+
`)
104+
return {
105+
code: output.toString(),
106+
map: output.generateMap({ hires: 'boundary' }),
107+
}
108+
}
109+
},
110+
},
111+
],
112+
})
113+
const runner = createServerModuleRunner(server.environments.ssr, {
114+
hmr: false,
115+
})
116+
const mod = await runner.import('/entry.mjs')
117+
expect(mod).toMatchInlineSnapshot(`
118+
{
119+
"depDefault": {
120+
"a": "a",
121+
"b": "b",
122+
},
123+
"depNamespace": {
124+
"a": "a",
125+
"b": "b",
126+
"default": {
127+
"a": "a",
128+
"b": "b",
129+
},
130+
},
131+
}
132+
`)
133+
})
86134
})
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exports.a = 'a'
2+
exports.b = 'b'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exports.a = 'a'
2+
exports.b = 'b'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import depDefault from './dep1.cjs'
2+
import * as depNamespace from './dep2.cjs'
3+
export { depDefault, depNamespace }

0 commit comments

Comments
 (0)