|
1 | 1 | import { PluginOption } from "vite"; |
2 | | -import { transform } from "./ts-transformer.js"; |
| 2 | +import {fileToTypes, invalidateOneFile, transform, typeToFile} from "./ts-transformer.js"; |
3 | 3 |
|
4 | 4 | // noinspection JSUnusedGlobalSymbols |
5 | 5 | /** |
@@ -27,6 +27,63 @@ export default function TsRuntimePickerVitePlugin(): PluginOption { |
27 | 27 |
|
28 | 28 | return null; |
29 | 29 | }, |
| 30 | + |
| 31 | + handleHotUpdate: ({server, file, timestamp}) => { |
| 32 | + const isKnownTypeDefinitionFile = [...typeToFile.values()].includes(file); |
| 33 | + |
| 34 | + if (!isKnownTypeDefinitionFile) { |
| 35 | + // This file change doesn't affect any of our transformations, so we can ignore it. |
| 36 | + return; |
| 37 | + } |
| 38 | + |
| 39 | + console.log(`[ts-runtime-picker] Change detected in a tracked type definition: ${file}`); |
| 40 | + |
| 41 | + |
| 42 | + // Surgically update the ts-morph project |
| 43 | + if (!invalidateOneFile(file)) return; |
| 44 | + |
| 45 | + const dependentModulesToUpdate = []; |
| 46 | + |
| 47 | + // Find all files (`userFile`) that import a type from the file that just changed (`file`). |
| 48 | + for (const [userFile, usedTypes] of fileToTypes.entries()) { |
| 49 | + for (const typeName of usedTypes) { |
| 50 | + if (typeToFile.get(typeName) === file) { |
| 51 | + // This `userFile` depends on the changed type. We need to update it. |
| 52 | + const moduleNode = server.moduleGraph.getModuleById(userFile); |
| 53 | + if (moduleNode) { |
| 54 | + dependentModulesToUpdate.push(moduleNode); |
| 55 | + // Once we know the file is affected, we don't need to check its other types. |
| 56 | + break; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + if (dependentModulesToUpdate.length > 0) { |
| 63 | + console.log(`[ts-runtime-picker] Found ${dependentModulesToUpdate.length} module(s) to update.`); |
| 64 | + |
| 65 | + //Invalidate modules and notify the client |
| 66 | + for (const mod of dependentModulesToUpdate) { |
| 67 | + server.moduleGraph.invalidateModule(mod); |
| 68 | + } |
| 69 | + |
| 70 | + // This sends the HMR update to the client (browser), telling it which |
| 71 | + // modules have changed so it can re-request them. |
| 72 | + server.ws.send({ |
| 73 | + type: 'update', |
| 74 | + updates: dependentModulesToUpdate.map((mod) => ({ |
| 75 | + type: 'js-update', |
| 76 | + path: mod.url, |
| 77 | + acceptedPath: mod.url, |
| 78 | + timestamp: timestamp |
| 79 | + })) |
| 80 | + }); |
| 81 | + } |
| 82 | + |
| 83 | + // We return the list of modules we've handled so Vite's core HMR logic |
| 84 | + // doesn't try to process them again. |
| 85 | + return dependentModulesToUpdate; |
| 86 | + } |
30 | 87 | } as PluginOption; |
31 | 88 | } |
32 | 89 |
|
|
0 commit comments