File tree 3 files changed +37
-7
lines changed
3 files changed +37
-7
lines changed Original file line number Diff line number Diff line change @@ -4,6 +4,7 @@ import type { HmrContext, ModuleNode } from 'vite'
4
4
import { isCSSRequest } from 'vite'
5
5
6
6
import {
7
+ cache ,
7
8
createDescriptor ,
8
9
getDescriptor ,
9
10
invalidateDescriptor ,
@@ -148,9 +149,20 @@ export async function handleHotUpdate(
148
149
updateType . push ( `style` )
149
150
}
150
151
if ( updateType . length ) {
151
- // invalidate the descriptor cache so that the next transform will
152
- // re-analyze the file and pick up the changes.
153
- invalidateDescriptor ( file )
152
+ if ( file . endsWith ( '.vue' ) ) {
153
+ // invalidate the descriptor cache so that the next transform will
154
+ // re-analyze the file and pick up the changes.
155
+ invalidateDescriptor ( file )
156
+ } else {
157
+ // https://github.com/vuejs/vitepress/issues/3129
158
+ // For non-vue files, e.g. .md files in VitePress, invalidating the
159
+ // descriptor will cause the main `load()` hook to attempt to read and
160
+ // parse a descriptor from a non-vue source file, leading to errors.
161
+ // To fix that we need to provide the descriptor we parsed here in the
162
+ // main cache. This assumes no other plugin is applying pre-transform to
163
+ // the file type - not impossible, but should be extremely unlikely.
164
+ cache . set ( file , descriptor )
165
+ }
154
166
debug ( `[vue:update(${ updateType . join ( '&' ) } )] ${ file } ` )
155
167
}
156
168
return [ ...affectedModules ] . filter ( Boolean ) as ModuleNode [ ]
Original file line number Diff line number Diff line change @@ -40,9 +40,22 @@ export async function transformMain(
40
40
const prevDescriptor = getPrevDescriptor ( filename )
41
41
const { descriptor, errors } = createDescriptor ( filename , code , options )
42
42
43
- if ( fs . existsSync ( filename ) )
44
- // set descriptor for HMR if it's not set yet
45
- getDescriptor ( filename , options , true , true )
43
+ if ( fs . existsSync ( filename ) ) {
44
+ // populate descriptor cache for HMR if it's not set yet
45
+ getDescriptor (
46
+ filename ,
47
+ options ,
48
+ true ,
49
+ true ,
50
+ // for vue files, create descriptor from fs read to be consistent with
51
+ // logic in handleHotUpdate()
52
+ // for non vue files, e.g. md files in vitepress, we assume
53
+ // `hmrContext.read` is overwriten so handleHotUpdate() is dealing with
54
+ // post-transform code, so we populate the descriptor with post-transform
55
+ // code here as well.
56
+ filename . endsWith ( '.vue' ) ? undefined : code ,
57
+ )
58
+ }
46
59
47
60
if ( errors . length ) {
48
61
errors . forEach ( ( error ) =>
Original file line number Diff line number Diff line change @@ -12,6 +12,10 @@ export interface SFCParseResult {
12
12
}
13
13
14
14
export const cache = new Map < string , SFCDescriptor > ( )
15
+ // we use a separate descriptor cache for HMR purposes.
16
+ // The main cached descriptors are parsed from SFCs that may have been
17
+ // transformed by other plugins, e.g. vue-macros;
18
+ // The HMR cached descriptors are based on the raw, pre-transform SFCs.
15
19
export const hmrCache = new Map < string , SFCDescriptor > ( )
16
20
const prevCache = new Map < string , SFCDescriptor | undefined > ( )
17
21
@@ -52,6 +56,7 @@ export function getDescriptor(
52
56
options : ResolvedOptions ,
53
57
createIfNotFound = true ,
54
58
hmr = false ,
59
+ code ?: string ,
55
60
) : SFCDescriptor | undefined {
56
61
const _cache = hmr ? hmrCache : cache
57
62
if ( _cache . has ( filename ) ) {
@@ -60,7 +65,7 @@ export function getDescriptor(
60
65
if ( createIfNotFound ) {
61
66
const { descriptor, errors } = createDescriptor (
62
67
filename ,
63
- fs . readFileSync ( filename , 'utf-8' ) ,
68
+ code ?? fs . readFileSync ( filename , 'utf-8' ) ,
64
69
options ,
65
70
hmr ,
66
71
)
You can’t perform that action at this time.
0 commit comments