Skip to content

Commit bbd98fc

Browse files
committed
feat: support 3.3 imported types hmr
1 parent 8407cf6 commit bbd98fc

File tree

3 files changed

+60
-11
lines changed

3 files changed

+60
-11
lines changed

src/pluginWebpack4.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { clientCache, typeDepToSFCMap } from './resolveScript'
55
import fs = require('fs')
66
import { compiler as vueCompiler } from './compiler'
77
import { descriptorCache } from './descriptorCache'
8+
import { needHMR } from './util'
89

910
const RuleSet = require('webpack/lib/RuleSet')
1011

@@ -117,16 +118,11 @@ class VueLoaderPlugin {
117118
...rules,
118119
]
119120

120-
// 3.3 HMR support
121-
const isServer =
122-
vueLoaderOptions.isServerBuild ?? compiler.options.target === 'node'
123-
const isProduction =
124-
compiler.options.mode === 'production' ||
125-
process.env.NODE_ENV === 'production'
126-
const needsHotReload =
127-
!isServer && !isProduction && vueLoaderOptions.hotReload !== false
128-
129-
if (needsHotReload && vueCompiler.invalidateTypeCache) {
121+
// 3.3 HMR support for imported types
122+
if (
123+
needHMR(vueLoaderOptions, compiler.options) &&
124+
vueCompiler.invalidateTypeCache
125+
) {
130126
let watcher: any
131127

132128
const WatchPack = require('watchpack')

src/pluginWebpack5.ts

+41
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as qs from 'querystring'
22
import type { VueLoaderOptions } from './'
33
import type { RuleSetRule, Compiler } from 'webpack'
4+
import { needHMR } from './util'
5+
import { clientCache, typeDepToSFCMap } from './resolveScript'
6+
import { compiler as vueCompiler } from './compiler'
7+
import { descriptorCache } from './descriptorCache'
48

59
const id = 'vue-loader-plugin'
610
const NS = 'vue-loader'
@@ -225,6 +229,43 @@ class VueLoaderPlugin {
225229
...clonedRules,
226230
...rules,
227231
]
232+
233+
// 3.3 HMR support for imported types
234+
if (
235+
needHMR(vueLoaderOptions, compiler.options) &&
236+
vueCompiler.invalidateTypeCache
237+
) {
238+
compiler.hooks.afterCompile.tap(id, (compilation) => {
239+
if (compilation.compiler === compiler) {
240+
for (const file of typeDepToSFCMap.keys()) {
241+
compilation.fileDependencies.add(file)
242+
}
243+
}
244+
})
245+
compiler.hooks.watchRun.tap(id, () => {
246+
if (!compiler.modifiedFiles) return
247+
for (const file of compiler.modifiedFiles) {
248+
vueCompiler.invalidateTypeCache(file)
249+
const affectedSFCs = typeDepToSFCMap.get(file)
250+
if (affectedSFCs) {
251+
for (const sfc of affectedSFCs) {
252+
// bust script resolve cache
253+
const desc = descriptorCache.get(sfc)
254+
if (desc) clientCache.delete(desc)
255+
// force update importing SFC
256+
// @ts-ignore
257+
compiler.fileTimestamps.set(sfc, {
258+
safeTime: Date.now(),
259+
timestamp: Date.now(),
260+
})
261+
}
262+
}
263+
}
264+
for (const file of compiler.removedFiles) {
265+
vueCompiler.invalidateTypeCache(file)
266+
}
267+
})
268+
}
228269
}
229270
}
230271

src/util.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1-
import type { LoaderContext } from 'webpack'
1+
import type { Compiler, LoaderContext } from 'webpack'
22
import type { SFCDescriptor, CompilerOptions } from 'vue/compiler-sfc'
33
import type { VueLoaderOptions } from '.'
44
import * as path from 'path'
55

6+
export function needHMR(
7+
vueLoaderOptions: VueLoaderOptions,
8+
compilerOptions: Compiler['options']
9+
) {
10+
const isServer =
11+
vueLoaderOptions.isServerBuild ?? compilerOptions.target === 'node'
12+
const isProduction =
13+
compilerOptions.mode === 'production' ||
14+
process.env.NODE_ENV === 'production'
15+
return !isServer && !isProduction && vueLoaderOptions.hotReload !== false
16+
}
17+
618
export function resolveTemplateTSOptions(
719
descriptor: SFCDescriptor,
820
options: VueLoaderOptions

0 commit comments

Comments
 (0)