Skip to content

Commit

Permalink
fix(hmr): duplicated modules because of query params mismatch (fixes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Sep 1, 2022
1 parent 091537c commit 86bf776
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 4 deletions.
11 changes: 9 additions & 2 deletions packages/vite/src/client/client.ts
Expand Up @@ -388,7 +388,12 @@ export function removeStyle(id: string): void {
}
}

async function fetchUpdate({ path, acceptedPath, timestamp }: Update) {
async function fetchUpdate({
path,
acceptedPath,
timestamp,
explicitImportRequired
}: Update) {
const mod = hotModulesMap.get(path)
if (!mod) {
// In a code-splitting project,
Expand All @@ -415,7 +420,9 @@ async function fetchUpdate({ path, acceptedPath, timestamp }: Update) {
/* @vite-ignore */
base +
path.slice(1) +
`?import&t=${timestamp}${query ? `&${query}` : ''}`
`?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${
query ? `&${query}` : ''
}`
)
moduleMap.set(dep, newMod)
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -76,7 +76,7 @@ export const canSkipImportAnalysis = (id: string): boolean =>
const optimizedDepChunkRE = /\/chunk-[A-Z0-9]{8}\.js/
const optimizedDepDynamicRE = /-[A-Z0-9]{8}\.js/

function isExplicitImportRequired(url: string) {
export function isExplicitImportRequired(url: string): boolean {
return !isJSRequest(cleanUrl(url)) && !isCSSRequest(url)
}

Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/server/hmr.ts
Expand Up @@ -9,6 +9,7 @@ import { createDebugger, normalizePath, unique } from '../utils'
import type { ViteDevServer } from '..'
import { isCSSRequest } from '../plugins/css'
import { getAffectedGlobModules } from '../plugins/importMetaGlob'
import { isExplicitImportRequired } from '../plugins/importAnalysis'
import type { ModuleNode } from './moduleGraph'

export const debugHmr = createDebugger('vite:hmr')
Expand Down Expand Up @@ -151,9 +152,13 @@ export function updateModules(

updates.push(
...[...boundaries].map(({ boundary, acceptedVia }) => ({
type: `${boundary.type}-update` as Update['type'],
type: `${boundary.type}-update` as const,
timestamp,
path: boundary.url,
explicitImportRequired:
boundary.type === 'js'
? isExplicitImportRequired(acceptedVia.url)
: undefined,
acceptedPath: acceptedVia.url
}))
)
Expand Down
4 changes: 4 additions & 0 deletions packages/vite/types/hmrPayload.d.ts
Expand Up @@ -20,6 +20,10 @@ export interface Update {
path: string
acceptedPath: string
timestamp: number
/**
* @internal
*/
explicitImportRequired: boolean | undefined
}

export interface PrunePayload {
Expand Down
26 changes: 26 additions & 0 deletions playground/hmr/__tests__/hmr.spec.ts
Expand Up @@ -218,6 +218,32 @@ if (!isBuild) {
expect(await btn.textContent()).toBe('Counter 1')
})

// #2255
test('importing reloaded', async () => {
await page.goto(viteTestUrl)
const outputEle = await page.$('.importing-reloaded')
const getOutput = () => {
return outputEle.innerHTML()
}

await untilUpdated(getOutput, ['a.js: a0', 'b.js: b0,a0'].join('<br>'))

editFile('importing-updated/a.js', (code) => code.replace("'a0'", "'a1'"))
await untilUpdated(
getOutput,
['a.js: a0', 'b.js: b0,a0', 'a.js: a1'].join('<br>')
)

editFile('importing-updated/b.js', (code) =>
code.replace('`b0,${a}`', '`b1,${a}`')
)
// note that "a.js: a1" should not happen twice after "b.js: b0,a0'"
await untilUpdated(
getOutput,
['a.js: a0', 'b.js: b0,a0', 'a.js: a1', 'b.js: b1,a1'].join('<br>')
)
})

describe('acceptExports', () => {
const HOT_UPDATED = /hot updated/
const CONNECTED = /connected/
Expand Down
1 change: 1 addition & 0 deletions playground/hmr/hmr.ts
@@ -1,4 +1,5 @@
import { foo as depFoo, nestedFoo } from './hmrDep'
import './importing-updated'

export const foo = 1
text('.app', foo)
Expand Down
8 changes: 8 additions & 0 deletions playground/hmr/importing-updated/a.js
@@ -0,0 +1,8 @@
const val = 'a0'
document.querySelector('.importing-reloaded').innerHTML += `a.js: ${val}<br>`

export default val

if (import.meta.hot) {
import.meta.hot.accept()
}
8 changes: 8 additions & 0 deletions playground/hmr/importing-updated/b.js
@@ -0,0 +1,8 @@
import a from './a.js'

const val = `b0,${a}`
document.querySelector('.importing-reloaded').innerHTML += `b.js: ${val}<br>`

if (import.meta.hot) {
import.meta.hot.accept()
}
2 changes: 2 additions & 0 deletions playground/hmr/importing-updated/index.js
@@ -0,0 +1,2 @@
import './a'
import './b'
1 change: 1 addition & 0 deletions playground/hmr/index.html
Expand Up @@ -25,3 +25,4 @@
<div class="link-tag-added">no</div>
<div class="link-tag-removed">no</div>
<div class="import-image"></div>
<div class="importing-reloaded"></div>

0 comments on commit 86bf776

Please sign in to comment.