-
Notifications
You must be signed in to change notification settings - Fork 29.5k
fix(Rspack): resolve HMR unresponsiveness or unexpected full reload & update dev snapshot #83480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
09a8b53
udpate Rspack snapshot
SyMind 527e32b
test/development/acceptance/ReactRefreshLogBox.test.ts
SyMind 72e808b
test/development/acceptance/ReactRefreshLogBox.test.ts
SyMind 76a6a56
update @rspack/plugin-react-refresh
SyMind c2d4658
test/development/acceptance-app/ReactRefreshLogBox.test.ts
SyMind 2174765
test/development/acceptance/ReactRefreshLogBox.test.ts
SyMind f4c7af7
test/development/acceptance/ReactRefreshLogBox-builtins.test.ts
SyMind d3ed1c7
server-component-next-dynamic-ssr-false.test.ts
SyMind bc56b91
font-loader-in-document-error.test.ts
SyMind 23dace3
prettier
SyMind 6e045cc
owner-stack.test.ts
SyMind bad8397
fix: test/development/basic/gssp-ssr-change-reloading/test/index.test.ts
SyMind 4474343
update snapshot
SyMind da6a3f8
fix: ai suggestions
SyMind 11ece96
fix: RspackReactRefresh
SyMind 8a5d4c3
fix typo
SyMind 2acb7ff
fix: remove stack in next/fount error
SyMind 966cabf
fix: update snapshot
SyMind 94967e8
fix: lint error
SyMind d6e377f
update snapshot test/development/acceptance/ReactRefreshLogBox.test.ts
SyMind b0304d2
fix: pnpm lock
SyMind 962bb3b
Merge branch 'canary' into update-snapshot
SyMind fd8cc1a
Merge branch 'canary' into update-snapshot
SyMind 2833007
fix: lint
SyMind File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import type { Compiler } from 'webpack' | ||
|
||
const PLUGIN_NAME = 'ReactRefreshRspackPlugin' | ||
|
||
class ReactRefreshRspackPlugin { | ||
static loader = 'builtin:react-refresh-loader' | ||
|
||
apply(compiler: Compiler) { | ||
new compiler.webpack.ProvidePlugin({ | ||
$ReactRefreshRuntime$: require.resolve('./internal/RspackReactRefresh'), | ||
}).apply(compiler) | ||
|
||
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { | ||
compilation.hooks.additionalTreeRuntimeRequirements.tap( | ||
PLUGIN_NAME, | ||
(_, runtimeRequirements) => { | ||
runtimeRequirements.add(compiler.webpack.RuntimeGlobals.moduleCache) | ||
} | ||
) | ||
}) | ||
} | ||
} | ||
|
||
export default ReactRefreshRspackPlugin |
96 changes: 96 additions & 0 deletions
96
packages/react-refresh-utils/internal/RspackReactRefresh.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import RefreshHelpers from './helpers' | ||
|
||
declare const __webpack_require__: { | ||
c: Record<string | number, { exports: unknown | (() => Promise<unknown>) }> | ||
} | ||
|
||
// Extracts exports from a webpack module object. | ||
function getModuleExports(moduleId: string) { | ||
if (typeof moduleId === 'undefined') { | ||
// `moduleId` is unavailable, which indicates that this module is not in the cache, | ||
// which means we won't be able to capture any exports, | ||
// and thus they cannot be refreshed safely. | ||
// These are likely runtime or dynamically generated modules. | ||
return {} | ||
} | ||
|
||
var maybeModule = __webpack_require__.c[moduleId] | ||
if (typeof maybeModule === 'undefined') { | ||
// `moduleId` is available but the module in cache is unavailable, | ||
// which indicates the module is somehow corrupted (e.g. broken Webpack `module` globals). | ||
// We will warn the user (as this is likely a mistake) and assume they cannot be refreshed. | ||
console.warn( | ||
'[React Refresh] Failed to get exports for module: ' + moduleId + '.' | ||
) | ||
return {} | ||
} | ||
|
||
var exportsOrPromise = maybeModule.exports | ||
if (typeof Promise !== 'undefined' && exportsOrPromise instanceof Promise) { | ||
return exportsOrPromise.then(function (exports) { | ||
return exports | ||
}) | ||
} | ||
return exportsOrPromise | ||
} | ||
|
||
function executeRuntime(moduleExports, moduleId, webpackHot) { | ||
RefreshHelpers.registerExportsForReactRefresh(moduleExports, moduleId) | ||
|
||
if (webpackHot) { | ||
var isHotUpdate = !!webpackHot.data | ||
var prevSignature: unknown[] | null = webpackHot.data?.prevSignature ?? null | ||
|
||
if (RefreshHelpers.isReactRefreshBoundary(moduleExports)) { | ||
webpackHot.dispose( | ||
// Save the previous exports signature on update so we can compare the boundary | ||
// signatures. We avoid saving exports themselves since it causes memory leaks (https://github.com/vercel/next.js/pull/53797) | ||
function hotDisposeCallback(data) { | ||
data.prevSignature = | ||
RefreshHelpers.getRefreshBoundarySignature(moduleExports) | ||
} | ||
) | ||
webpackHot.accept() | ||
|
||
// This field is set when the previous version of this module was a | ||
// Refresh Boundary, letting us know we need to check for invalidation or | ||
// enqueue an update. | ||
if (prevSignature !== null) { | ||
if (isHotUpdate) { | ||
if ( | ||
RefreshHelpers.shouldInvalidateReactRefreshBoundary( | ||
prevSignature, | ||
RefreshHelpers.getRefreshBoundarySignature(moduleExports) | ||
) | ||
) { | ||
webpackHot.invalidate() | ||
} else { | ||
RefreshHelpers.scheduleUpdate() | ||
} | ||
} | ||
} | ||
} else { | ||
if (isHotUpdate && prevSignature !== null) { | ||
webpackHot.invalidate() | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Port from https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/loader/utils/getRefreshModuleRuntime.js#L29 | ||
export function refresh(moduleId, webpackHot) { | ||
SyMind marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const currentExports = getModuleExports(moduleId) | ||
const fn = (exports) => { | ||
executeRuntime(exports, moduleId, webpackHot) | ||
} | ||
if (typeof Promise !== 'undefined' && currentExports instanceof Promise) { | ||
currentExports.then(fn) | ||
} else { | ||
fn(currentExports) | ||
} | ||
} | ||
|
||
export { | ||
register, | ||
createSignatureFunctionForTransform, | ||
} from 'react-refresh/runtime' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import RefreshRuntime from 'react-refresh/runtime' | ||
import type { RefreshRuntimeGlobals } from './runtime' | ||
|
||
declare const self: Window & RefreshRuntimeGlobals | ||
|
||
if (typeof self !== 'undefined') { | ||
var $RefreshInjected$ = '__reactRefreshInjected' | ||
|
||
// Only inject the runtime if it hasn't been injected | ||
if (!self[$RefreshInjected$]) { | ||
RefreshRuntime.injectIntoGlobalHook(self) | ||
|
||
// Empty implementation to avoid "ReferenceError: variable is not defined" in module which didn't pass builtin:react-refresh-loader | ||
self.$RefreshSig$ = () => (type) => type | ||
self.$RefreshReg$ = () => {} | ||
|
||
// Mark the runtime as injected to prevent double-injection | ||
self[$RefreshInjected$] = true | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.