diff --git a/packages/next/src/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts b/packages/next/src/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts index 786b24ca4601d..c66019a762910 100644 --- a/packages/next/src/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts +++ b/packages/next/src/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts @@ -1,69 +1,12 @@ import type { webpack } from 'next/dist/compiled/webpack/webpack' +import { deleteCache } from '../../../server/dev/require-cache' import { clearModuleContext } from '../../../server/web/sandbox' -import { realpathSync } from '../../../lib/realpath' import path from 'path' -import isError from '../../../lib/is-error' -import { clearManifestCache } from '../../../server/load-manifest' type Compiler = webpack.Compiler type WebpackPluginInstance = webpack.WebpackPluginInstance -const originModules = [ - require.resolve('../../../server/require'), - require.resolve('../../../server/load-components'), - require.resolve('../../../server/next-server'), - require.resolve('next/dist/compiled/next-server/app-page.runtime.dev.js'), - require.resolve('next/dist/compiled/next-server/app-route.runtime.dev.js'), - require.resolve('next/dist/compiled/next-server/pages.runtime.dev.js'), - require.resolve('next/dist/compiled/next-server/pages-api.runtime.dev.js'), -] - const RUNTIME_NAMES = ['webpack-runtime', 'webpack-api-runtime'] - -function deleteFromRequireCache(filePath: string) { - try { - filePath = realpathSync(filePath) - } catch (e) { - if (isError(e) && e.code !== 'ENOENT') throw e - } - const mod = require.cache[filePath] - if (mod) { - // remove the child reference from the originModules - for (const originModule of originModules) { - const parent = require.cache[originModule] - if (parent) { - const idx = parent.children.indexOf(mod) - if (idx >= 0) parent.children.splice(idx, 1) - } - } - // remove parent references from external modules - for (const child of mod.children) { - child.parent = null - } - delete require.cache[filePath] - return true - } - return false -} - -export function deleteAppClientCache() { - deleteFromRequireCache( - require.resolve('next/dist/compiled/next-server/app-page.runtime.dev.js') - ) - deleteFromRequireCache( - require.resolve( - 'next/dist/compiled/next-server/app-page-experimental.runtime.dev.js' - ) - ) -} - -export function deleteCache(filePath: string) { - // try to clear it from the fs cache - clearManifestCache(filePath) - - deleteFromRequireCache(filePath) -} - const PLUGIN_NAME = 'NextJsRequireCacheHotReloader' // This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files. diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index 7b4f01eb69722..d5ffa3a869078 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -31,10 +31,7 @@ import { BLOCKED_PAGES } from '../../shared/lib/constants' import { getOverlayMiddleware } from '../../client/components/react-dev-overlay/server/middleware-turbopack' import { PageNotFoundError } from '../../shared/lib/utils' import { debounce } from '../utils' -import { - deleteAppClientCache, - deleteCache, -} from '../../build/webpack/plugins/nextjs-require-cache-hot-reloader' +import { deleteAppClientCache, deleteCache } from './require-cache' import { clearAllModuleContexts, clearModuleContext, diff --git a/packages/next/src/server/dev/require-cache.ts b/packages/next/src/server/dev/require-cache.ts new file mode 100644 index 0000000000000..a696438e4605d --- /dev/null +++ b/packages/next/src/server/dev/require-cache.ts @@ -0,0 +1,46 @@ +import isError from '../../lib/is-error' +import { realpathSync } from '../../lib/realpath' +import { clearManifestCache } from '../load-manifest' + +function deleteFromRequireCache(filePath: string) { + try { + filePath = realpathSync(filePath) + } catch (e) { + if (isError(e) && e.code !== 'ENOENT') throw e + } + const mod = require.cache[filePath] + if (mod) { + // remove the child reference from all parent modules + for (const parent of Object.values(require.cache)) { + if (parent?.children) { + const idx = parent.children.indexOf(mod) + if (idx >= 0) parent.children.splice(idx, 1) + } + } + // remove parent references from external modules + for (const child of mod.children) { + child.parent = null + } + delete require.cache[filePath] + return true + } + return false +} + +export function deleteAppClientCache() { + deleteFromRequireCache( + require.resolve('next/dist/compiled/next-server/app-page.runtime.dev.js') + ) + deleteFromRequireCache( + require.resolve( + 'next/dist/compiled/next-server/app-page-experimental.runtime.dev.js' + ) + ) +} + +export function deleteCache(filePath: string) { + // try to clear it from the fs cache + clearManifestCache(filePath) + + deleteFromRequireCache(filePath) +} diff --git a/packages/next/src/server/dev/turbopack/manifest-loader.ts b/packages/next/src/server/dev/turbopack/manifest-loader.ts index 64af684d85ed5..ce5526d14b624 100644 --- a/packages/next/src/server/dev/turbopack/manifest-loader.ts +++ b/packages/next/src/server/dev/turbopack/manifest-loader.ts @@ -27,7 +27,7 @@ import { import { join, posix } from 'path' import { readFile, writeFile } from 'fs/promises' import type { SetupOpts } from '../../lib/router-utils/setup-dev-bundler' -import { deleteCache } from '../../../build/webpack/plugins/nextjs-require-cache-hot-reloader' +import { deleteCache } from '../require-cache' import { writeFileAtomic } from '../../../lib/fs/write-atomic' import { isInterceptionRouteRewrite } from '../../../lib/generate-interception-routes-rewrites' import { diff --git a/packages/next/src/server/lib/render-server.ts b/packages/next/src/server/lib/render-server.ts index ddfe5fca9ca7b..206b238018c83 100644 --- a/packages/next/src/server/lib/render-server.ts +++ b/packages/next/src/server/lib/render-server.ts @@ -20,13 +20,9 @@ let initializations: Record< > = {} let sandboxContext: undefined | typeof import('../web/sandbox/context') -let requireCacheHotReloader: - | undefined - | typeof import('../../build/webpack/plugins/nextjs-require-cache-hot-reloader') if (process.env.NODE_ENV !== 'production') { sandboxContext = require('../web/sandbox/context') - requireCacheHotReloader = require('../../build/webpack/plugins/nextjs-require-cache-hot-reloader') } export function clearAllModuleContexts() { @@ -37,16 +33,6 @@ export function clearModuleContext(target: string) { return sandboxContext?.clearModuleContext(target) } -export function deleteAppClientCache() { - return requireCacheHotReloader?.deleteAppClientCache() -} - -export function deleteCache(filePaths: string[]) { - for (const filePath of filePaths) { - requireCacheHotReloader?.deleteCache(filePath) - } -} - export async function getServerField( dir: string, field: PropagateToWorkersField diff --git a/packages/next/src/server/lib/router-server.ts b/packages/next/src/server/lib/router-server.ts index 70be360d51035..01de5abfa5f39 100644 --- a/packages/next/src/server/lib/router-server.ts +++ b/packages/next/src/server/lib/router-server.ts @@ -54,9 +54,7 @@ const isNextFont = (pathname: string | null) => export type RenderServer = Pick< typeof import('./render-server'), | 'initialize' - | 'deleteCache' | 'clearModuleContext' - | 'deleteAppClientCache' | 'propagateServerField' | 'getServerField' >