|
1 | 1 | import * as qs from 'querystring'
|
2 | 2 | import type { VueLoaderOptions } from './'
|
3 | 3 | 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' |
4 | 8 |
|
5 | 9 | const id = 'vue-loader-plugin'
|
6 | 10 | const NS = 'vue-loader'
|
@@ -225,6 +229,43 @@ class VueLoaderPlugin {
|
225 | 229 | ...clonedRules,
|
226 | 230 | ...rules,
|
227 | 231 | ]
|
| 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 | + } |
228 | 269 | }
|
229 | 270 | }
|
230 | 271 |
|
|
0 commit comments