Skip to content

Commit c923953

Browse files
committed
fix(plugin-rsc): use MagicString to preserve sourcemap chain in webpack-require transform
Returning `map: null` from a transform that changes string lengths breaks the Rollup sourcemap chain. This causes Rollup/Vite to emit noisy 'Can't resolve original location of error' warnings for every file that passes through this transform — in practice, every module that contains '__webpack_require__', which includes all 'use client' component files processed by the RSC pipeline. Replace the manual string replacements + `map: null` with MagicString, which generates a correct sourcemap that reflects the actual character offset changes (`__webpack_require__` → `__vite_rsc_require__` is not a same-length replacement). A single regex pass handles both the `.u` variant and bare `__webpack_require__` without overlapping overwrites. Fixes: 'Can't resolve original location of error' build warnings
1 parent 377cfda commit c923953

1 file changed

Lines changed: 34 additions & 16 deletions

File tree

packages/plugin-rsc/src/core/plugin.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import MagicString from 'magic-string'
12
import type { Plugin } from 'vite'
23

34
export default function vitePluginRscCore(): Plugin[] {
@@ -6,25 +7,42 @@ export default function vitePluginRscCore(): Plugin[] {
67
name: 'rsc:patch-react-server-dom-webpack',
78
transform: {
89
filter: { code: '__webpack_require__' },
9-
handler(originalCode, _id, _options) {
10-
let code = originalCode
11-
if (code.includes('__webpack_require__.u')) {
12-
// avoid accessing `__webpack_require__` on import side effect
13-
// https://github.com/facebook/react/blob/a9bbe34622885ef5667d33236d580fe7321c0d8b/packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser.js#L16-L17
14-
code = code.replaceAll('__webpack_require__.u', '({}).u')
15-
}
10+
handler(code, id, _options) {
11+
if (!code.includes('__webpack_require__')) return
12+
13+
// Use MagicString to perform replacements with a proper sourcemap,
14+
// so the Rollup sourcemap chain stays intact and doesn't emit
15+
// 'Can't resolve original location of error' warnings for every
16+
// file processed by this transform (e.g. all "use client" modules).
17+
const s = new MagicString(code)
1618

17-
// the existance of `__webpack_require__` global can break some packages
18-
// https://github.com/TooTallNate/node-bindings/blob/c8033dcfc04c34397384e23f7399a30e6c13830d/bindings.js#L90-L94
19-
if (code.includes('__webpack_require__')) {
20-
code = code.replaceAll(
21-
'__webpack_require__',
22-
'__vite_rsc_require__',
23-
)
19+
// Match `__webpack_require__.u` first (longer pattern), then bare
20+
// `__webpack_require__`, in a single left-to-right pass to avoid
21+
// overlapping overwrites into MagicString.
22+
const re = /__webpack_require__(?:\.u)?/g
23+
let match: RegExpExecArray | null
24+
while ((match = re.exec(code)) !== null) {
25+
const { index } = match
26+
if (match[0] === '__webpack_require__.u') {
27+
// avoid accessing `__webpack_require__` on import side effect
28+
// https://github.com/facebook/react/blob/a9bbe34622885ef5667d33236d580fe7321c0d8b/packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser.js#L16-L17
29+
s.overwrite(index, index + match[0].length, '({}).u')
30+
} else {
31+
// the existance of `__webpack_require__` global can break some packages
32+
// https://github.com/TooTallNate/node-bindings/blob/c8033dcfc04c34397384e23f7399a30e6c13830d/bindings.js#L90-L94
33+
s.overwrite(
34+
index,
35+
index + match[0].length,
36+
'__vite_rsc_require__',
37+
)
38+
}
2439
}
2540

26-
if (code !== originalCode) {
27-
return { code, map: null }
41+
if (s.hasChanged()) {
42+
return {
43+
code: s.toString(),
44+
map: s.generateMap({ hires: true, source: id }),
45+
}
2846
}
2947
},
3048
},

0 commit comments

Comments
 (0)