Skip to content

Commit

Permalink
fix(plugin-vue): distinguish HMR and transform descriptor (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz authored Aug 14, 2023
1 parent 729181c commit aa2b59d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
11 changes: 6 additions & 5 deletions packages/plugin-vue/src/handleHotUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { isCSSRequest } from 'vite'
import {
createDescriptor,
getDescriptor,
setPrevDescriptor,
invalidateDescriptor,
} from './utils/descriptorCache'
import {
getResolvedScript,
Expand All @@ -26,16 +26,14 @@ export async function handleHotUpdate(
{ file, modules, read }: HmrContext,
options: ResolvedOptions,
): Promise<ModuleNode[] | void> {
const prevDescriptor = getDescriptor(file, options, false)
const prevDescriptor = getDescriptor(file, options, false, true)
if (!prevDescriptor) {
// file hasn't been requested yet (e.g. async component)
return
}

setPrevDescriptor(file, prevDescriptor)

const content = await read()
const { descriptor } = createDescriptor(file, content, options)
const { descriptor } = createDescriptor(file, content, options, true)

let needRerender = false
const affectedModules = new Set<ModuleNode | undefined>()
Expand Down Expand Up @@ -150,6 +148,9 @@ export async function handleHotUpdate(
updateType.push(`style`)
}
if (updateType.length) {
// invalidate the descriptor cache so that the next transform will
// re-analyze the file and pick up the changes.
invalidateDescriptor(file)
debug(`[vue:update(${updateType.join('&')})] ${file}`)
}
return [...affectedModules].filter(Boolean) as ModuleNode[]
Expand Down
5 changes: 4 additions & 1 deletion packages/plugin-vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { addMapping, fromMap, toEncodedMap } from '@jridgewell/gen-mapping'
import { normalizePath, transformWithEsbuild } from 'vite'
import {
createDescriptor,
getDescriptor,
getPrevDescriptor,
setSrcDescriptor,
} from './utils/descriptorCache'
Expand All @@ -35,10 +36,12 @@ export async function transformMain(
) {
const { devServer, isProduction, devToolsEnabled } = options

// prev descriptor is only set and used for hmr
const prevDescriptor = getPrevDescriptor(filename)
const { descriptor, errors } = createDescriptor(filename, code, options)

// set descriptor for HMR if it's not set yet
getDescriptor(filename, options, true, true)

if (errors.length) {
errors.forEach((error) =>
pluginContext.error(createRollupError(filename, error)),
Expand Down
24 changes: 15 additions & 9 deletions packages/plugin-vue/src/utils/descriptorCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export interface SFCParseResult {
}

export const cache = new Map<string, SFCDescriptor>()
export const hmrCache = new Map<string, SFCDescriptor>()
const prevCache = new Map<string, SFCDescriptor | undefined>()

export function createDescriptor(
filename: string,
source: string,
{ root, isProduction, sourceMap, compiler }: ResolvedOptions,
hmr = false,
): SFCParseResult {
const { descriptor, errors } = compiler.parse(source, {
filename,
Expand All @@ -28,35 +30,39 @@ export function createDescriptor(
// project (relative to root) and on different systems.
const normalizedPath = slash(path.normalize(path.relative(root, filename)))
descriptor.id = getHash(normalizedPath + (isProduction ? source : ''))

cache.set(filename, descriptor)
;(hmr ? hmrCache : cache).set(filename, descriptor)
return { descriptor, errors }
}

export function getPrevDescriptor(filename: string): SFCDescriptor | undefined {
return prevCache.get(filename)
}

export function setPrevDescriptor(
filename: string,
entry: SFCDescriptor,
): void {
prevCache.set(filename, entry)
export function invalidateDescriptor(filename: string, hmr = false): void {
const _cache = hmr ? hmrCache : cache
const prev = _cache.get(filename)
_cache.delete(filename)
if (prev) {
prevCache.set(filename, prev)
}
}

export function getDescriptor(
filename: string,
options: ResolvedOptions,
createIfNotFound = true,
hmr = false,
): SFCDescriptor | undefined {
if (cache.has(filename)) {
return cache.get(filename)!
const _cache = hmr ? hmrCache : cache
if (_cache.has(filename)) {
return _cache.get(filename)!
}
if (createIfNotFound) {
const { descriptor, errors } = createDescriptor(
filename,
fs.readFileSync(filename, 'utf-8'),
options,
hmr,
)
if (errors.length) {
throw errors[0]
Expand Down

0 comments on commit aa2b59d

Please sign in to comment.