File tree Expand file tree Collapse file tree 3 files changed +37
-7
lines changed Expand file tree Collapse file tree 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'
44import { isCSSRequest } from 'vite'
55
66import {
7+ cache ,
78 createDescriptor ,
89 getDescriptor ,
910 invalidateDescriptor ,
@@ -148,9 +149,20 @@ export async function handleHotUpdate(
148149 updateType . push ( `style` )
149150 }
150151 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+ }
154166 debug ( `[vue:update(${ updateType . join ( '&' ) } )] ${ file } ` )
155167 }
156168 return [ ...affectedModules ] . filter ( Boolean ) as ModuleNode [ ]
Original file line number Diff line number Diff line change @@ -40,9 +40,22 @@ export async function transformMain(
4040 const prevDescriptor = getPrevDescriptor ( filename )
4141 const { descriptor, errors } = createDescriptor ( filename , code , options )
4242
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+ }
4659
4760 if ( errors . length ) {
4861 errors . forEach ( ( error ) =>
Original file line number Diff line number Diff line change @@ -12,6 +12,10 @@ export interface SFCParseResult {
1212}
1313
1414export 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.
1519export const hmrCache = new Map < string , SFCDescriptor > ( )
1620const prevCache = new Map < string , SFCDescriptor | undefined > ( )
1721
@@ -52,6 +56,7 @@ export function getDescriptor(
5256 options : ResolvedOptions ,
5357 createIfNotFound = true ,
5458 hmr = false ,
59+ code ?: string ,
5560) : SFCDescriptor | undefined {
5661 const _cache = hmr ? hmrCache : cache
5762 if ( _cache . has ( filename ) ) {
@@ -60,7 +65,7 @@ export function getDescriptor(
6065 if ( createIfNotFound ) {
6166 const { descriptor, errors } = createDescriptor (
6267 filename ,
63- fs . readFileSync ( filename , 'utf-8' ) ,
68+ code ?? fs . readFileSync ( filename , 'utf-8' ) ,
6469 options ,
6570 hmr ,
6671 )
You can’t perform that action at this time.
0 commit comments