2021-10-24 23:04:26 +02:00
|
|
|
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
|
2021-11-26 13:06:41 +01:00
|
|
|
import { clearModuleContext } from '../../../server/web/sandbox'
|
2019-03-15 00:22:57 +01:00
|
|
|
import { realpathSync } from 'fs'
|
2020-07-01 17:34:00 +02:00
|
|
|
import path from 'path'
|
2021-09-16 18:06:57 +02:00
|
|
|
import isError from '../../../lib/is-error'
|
2019-03-10 05:27:33 +01:00
|
|
|
|
2021-10-24 23:04:26 +02:00
|
|
|
type Compiler = webpack5.Compiler
|
|
|
|
type WebpackPluginInstance = webpack5.WebpackPluginInstance
|
|
|
|
|
2021-05-05 11:26:36 +02:00
|
|
|
const originModules = [
|
2021-06-30 13:44:40 +02:00
|
|
|
require.resolve('../../../server/require'),
|
|
|
|
require.resolve('../../../server/load-components'),
|
2021-05-05 11:26:36 +02:00
|
|
|
]
|
|
|
|
|
2021-09-17 21:20:09 +02:00
|
|
|
const RUNTIME_NAMES = ['webpack-runtime', 'webpack-api-runtime']
|
|
|
|
|
2020-07-01 17:34:00 +02:00
|
|
|
function deleteCache(filePath: string) {
|
2019-03-15 00:22:57 +01:00
|
|
|
try {
|
2021-05-05 11:26:36 +02:00
|
|
|
filePath = realpathSync(filePath)
|
2019-05-29 13:57:26 +02:00
|
|
|
} catch (e) {
|
2021-09-16 18:06:57 +02:00
|
|
|
if (isError(e) && e.code !== 'ENOENT') throw e
|
2019-03-15 00:22:57 +01:00
|
|
|
}
|
2021-05-05 11:26:36 +02:00
|
|
|
const module = require.cache[filePath]
|
|
|
|
if (module) {
|
|
|
|
// remove the child reference from the originModules
|
|
|
|
for (const originModule of originModules) {
|
|
|
|
const parent = require.cache[originModule]
|
|
|
|
if (parent) {
|
|
|
|
const idx = parent.children.indexOf(module)
|
|
|
|
if (idx >= 0) parent.children.splice(idx, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// remove parent references from external modules
|
|
|
|
for (const child of module.children) {
|
|
|
|
child.parent = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete require.cache[filePath]
|
2018-07-24 11:24:40 +02:00
|
|
|
}
|
|
|
|
|
2020-06-27 19:16:55 +02:00
|
|
|
const PLUGIN_NAME = 'NextJsRequireCacheHotReloader'
|
|
|
|
|
2018-07-24 11:24:40 +02:00
|
|
|
// This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files.
|
2021-10-20 19:52:11 +02:00
|
|
|
export class NextJsRequireCacheHotReloader implements WebpackPluginInstance {
|
2019-03-15 00:22:57 +01:00
|
|
|
prevAssets: any = null
|
2020-06-27 19:16:55 +02:00
|
|
|
previousOutputPathsWebpack5: Set<string> = new Set()
|
|
|
|
currentOutputPathsWebpack5: Set<string> = new Set()
|
2019-03-15 00:22:57 +01:00
|
|
|
|
2021-10-20 19:52:11 +02:00
|
|
|
apply(compiler: Compiler) {
|
2021-10-07 01:46:46 +02:00
|
|
|
compiler.hooks.assetEmitted.tap(
|
|
|
|
PLUGIN_NAME,
|
2021-10-20 19:52:11 +02:00
|
|
|
(_file, { targetPath, content }) => {
|
2021-10-07 01:46:46 +02:00
|
|
|
this.currentOutputPathsWebpack5.add(targetPath)
|
|
|
|
deleteCache(targetPath)
|
2021-11-26 13:06:41 +01:00
|
|
|
clearModuleContext(targetPath, content.toString('utf-8'))
|
2021-10-07 01:46:46 +02:00
|
|
|
}
|
|
|
|
)
|
2020-07-01 17:34:00 +02:00
|
|
|
|
2021-10-07 01:46:46 +02:00
|
|
|
compiler.hooks.afterEmit.tap(PLUGIN_NAME, (compilation) => {
|
|
|
|
RUNTIME_NAMES.forEach((name) => {
|
|
|
|
const runtimeChunkPath = path.join(
|
2021-10-20 19:52:11 +02:00
|
|
|
compilation.outputOptions.path!,
|
2021-10-07 01:46:46 +02:00
|
|
|
`${name}.js`
|
2020-06-27 19:16:55 +02:00
|
|
|
)
|
2021-10-07 01:46:46 +02:00
|
|
|
deleteCache(runtimeChunkPath)
|
2020-06-27 19:16:55 +02:00
|
|
|
})
|
2021-01-01 18:39:39 +01:00
|
|
|
|
2021-10-07 01:46:46 +02:00
|
|
|
// we need to make sure to clear all server entries from cache
|
|
|
|
// since they can have a stale webpack-runtime cache
|
|
|
|
// which needs to always be in-sync
|
|
|
|
const entries = [...compilation.entries.keys()].filter((entry) =>
|
|
|
|
entry.toString().startsWith('pages/')
|
2021-01-01 18:39:39 +01:00
|
|
|
)
|
2020-06-27 19:16:55 +02:00
|
|
|
|
2021-10-07 01:46:46 +02:00
|
|
|
entries.forEach((page) => {
|
|
|
|
const outputPath = path.join(
|
2021-10-20 19:52:11 +02:00
|
|
|
compilation.outputOptions.path!,
|
2021-10-07 01:46:46 +02:00
|
|
|
page + '.js'
|
|
|
|
)
|
|
|
|
deleteCache(outputPath)
|
|
|
|
})
|
2020-06-27 19:16:55 +02:00
|
|
|
})
|
2021-10-07 01:46:46 +02:00
|
|
|
|
|
|
|
this.previousOutputPathsWebpack5 = new Set(this.currentOutputPathsWebpack5)
|
|
|
|
this.currentOutputPathsWebpack5.clear()
|
2018-07-24 11:24:40 +02:00
|
|
|
}
|
|
|
|
}
|