Skip to content

Commit 59714db

Browse files
authored
Update server-only changes HMR handling (#34298)
* Update server-only changes HMR handling * Add failing tests for GS(S)P server only changes * update test * normalize backslashes * Update to xor the chunk hashes * remove test change * remove other test change
1 parent d288d43 commit 59714db

File tree

9 files changed

+365
-212
lines changed

9 files changed

+365
-212
lines changed

packages/next/server/dev/hot-reloader.ts

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IncomingMessage, ServerResponse } from 'http'
33
import { WebpackHotMiddleware } from './hot-middleware'
44
import { join, relative, isAbsolute } from 'path'
55
import { UrlObject } from 'url'
6-
import { webpack } from 'next/dist/compiled/webpack/webpack'
6+
import { webpack, StringXor } from 'next/dist/compiled/webpack/webpack'
77
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
88
import {
99
createEntrypoints,
@@ -594,21 +594,56 @@ export default class HotReloader {
594594
const trackPageChanges =
595595
(pageHashMap: Map<string, string>, changedItems: Set<string>) =>
596596
(stats: webpack5.Compilation) => {
597-
stats.entrypoints.forEach((entry, key) => {
598-
if (key.startsWith('pages/')) {
599-
// TODO this doesn't handle on demand loaded chunks
600-
entry.chunks.forEach((chunk: any) => {
601-
if (chunk.id === key) {
602-
const prevHash = pageHashMap.get(key)
603-
604-
if (prevHash && prevHash !== chunk.hash) {
605-
changedItems.add(key)
597+
try {
598+
stats.entrypoints.forEach((entry, key) => {
599+
if (key.startsWith('pages/')) {
600+
// TODO this doesn't handle on demand loaded chunks
601+
entry.chunks.forEach((chunk) => {
602+
if (chunk.id === key) {
603+
const modsIterable: any =
604+
stats.chunkGraph.getChunkModulesIterable(chunk)
605+
606+
let chunksHash = new StringXor()
607+
608+
modsIterable.forEach((mod: any) => {
609+
if (
610+
mod.resource &&
611+
mod.resource.replace(/\\/g, '/').includes(key)
612+
) {
613+
// use original source to calculate hash since mod.hash
614+
// includes the source map in development which changes
615+
// every time for both server and client so we calculate
616+
// the hash without the source map for the page module
617+
const hash = require('crypto')
618+
.createHash('sha256')
619+
.update(mod.originalSource().buffer())
620+
.digest()
621+
.toString('hex')
622+
623+
chunksHash.add(hash)
624+
} else {
625+
// for non-pages we can use the module hash directly
626+
const hash = stats.chunkGraph.getModuleHash(
627+
mod,
628+
chunk.runtime
629+
)
630+
chunksHash.add(hash)
631+
}
632+
})
633+
const prevHash = pageHashMap.get(key)
634+
const curHash = chunksHash.toString()
635+
636+
if (prevHash && prevHash !== curHash) {
637+
changedItems.add(key)
638+
}
639+
pageHashMap.set(key, curHash)
606640
}
607-
pageHashMap.set(key, chunk.hash)
608-
}
609-
})
610-
}
611-
})
641+
})
642+
}
643+
})
644+
} catch (err) {
645+
console.error(err)
646+
}
612647
}
613648

614649
multiCompiler.compilers[0].hooks.emit.tap(

packages/next/types/webpack.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ declare module 'next/dist/compiled/webpack/webpack' {
3535
export let BasicEvaluatedExpression: any
3636
export let GraphHelpers: any
3737
export let sources: typeof webpackSources
38+
export let StringXor: any
3839
// TODO change this to webpack5
3940
export { webpack4 as webpack, loader, webpack4, webpack5 }
4041
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"hello": "world"
3+
}

test/integration/gssp-ssr-change-reloading/pages/index.js renamed to test/development/basic/gssp-ssr-change-reloading/pages/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useRouter } from 'next/router'
2+
import data from '../lib/data.json'
23

34
export default function Gsp(props) {
45
if (useRouter().isFallback) {
@@ -19,6 +20,7 @@ export const getStaticProps = async () => {
1920
return {
2021
props: {
2122
count,
23+
data,
2224
random: Math.random(),
2325
},
2426
}

0 commit comments

Comments
 (0)