From 702b7cb646c0a3984633dce6c071395d796bf84c Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 5 Aug 2026 12:46:16 -0700 Subject: [PATCH] Fix vite HMR for vue2 --- vite.config.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/vite.config.js b/vite.config.js index e3aba44a6e..119f8091d5 100644 --- a/vite.config.js +++ b/vite.config.js @@ -25,6 +25,30 @@ const stylesImporter = { }, }; +/** + * Tailwind's `content` globs make every SFC a PostCSS dependency of + * tailwind.css, so Vite registers an extra `type: 'asset'` node under each + * SFC's path. plugin-vue2 treats the first node without a `type=` query as the + * SFC's main module and picks that asset node, sending the hot update to + * tailwind.css instead of the component. + */ +const vue2HmrMainModuleFix = { + name: 'pm:vue2-hmr-main-module-fix', + enforce: 'post', + hotUpdate({ file, modules }) { + if (!file.endsWith('.vue') || !modules.some((mod) => mod.type === 'asset')) { + return; + } + + const candidates = this.environment.moduleGraph.getModulesByFile(file) ?? []; + const mainModule = [...candidates].find( + (mod) => mod.type !== 'asset' && !/type=/.test(mod.url), + ); + + return mainModule ? [...modules, mainModule] : undefined; + }, +}; + /** * Vite runs in parallel with Laravel Mix. * Mix continues to own public/css/* for legacy layouts; Vite compiles the same @@ -78,6 +102,7 @@ export default defineConfig(({ mode }) => { }, }, }), + vue2HmrMainModuleFix, ], resolve: { extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],