@vanilla-extract/vite-plugin 5.2.0 → 5.2.1-vite-hmr-fix-20260318112727

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,6 +41,7 @@ function vanillaExtractPlugin({
41
41
  let compiler$1;
42
42
  let isBuild;
43
43
  const vitePromise = import('vite');
44
+ const transformedModules = new Set();
44
45
  const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
45
46
  const getAbsoluteId = filePath => {
46
47
  let resolvedId = filePath;
@@ -55,21 +56,37 @@ function vanillaExtractPlugin({
55
56
  }
56
57
  return integration.normalizePath(resolvedId);
57
58
  };
58
- function invalidateModule(absoluteId) {
59
- if (!server) return;
59
+
60
+ /**
61
+ * Custom invalidation function that takes a chain of importers to invalidate. If an importer is a
62
+ * VE module, its virtual CSS is invalidated instead. Otherwise, the module is invalidated
63
+ * normally.
64
+ */
65
+ const invalidateImporterChain = ({
66
+ importerChain,
67
+ server,
68
+ timestamp
69
+ }) => {
60
70
  const {
61
71
  moduleGraph
62
72
  } = server;
63
- const modules = moduleGraph.getModulesByFile(absoluteId);
64
- if (modules) {
65
- for (const module of modules) {
66
- moduleGraph.invalidateModule(module);
67
-
68
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
69
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
73
+ const seen = new Set();
74
+ for (const mod of importerChain) {
75
+ if (mod.id && integration.cssFileFilter.test(mod.id)) {
76
+ const virtualModules = moduleGraph.getModulesByFile(fileIdToVirtualId(mod.id));
77
+ for (const virtualModule of virtualModules ?? []) {
78
+ moduleGraph.invalidateModule(virtualModule, seen, timestamp, true);
79
+ }
80
+ } else if (mod.id) {
81
+ // `mod` is from the compiler's internal Vite server, so look up the
82
+ // corresponding module in the consuming server's graph by ID
83
+ const serverMod = moduleGraph.getModuleById(mod.id);
84
+ if (serverMod) {
85
+ moduleGraph.invalidateModule(serverMod, seen, timestamp, true);
86
+ }
70
87
  }
71
88
  }
72
- }
89
+ };
73
90
  return [{
74
91
  name: `${PLUGIN_NAMESPACE}-inline-dev-css`,
75
92
  apply: (_, {
@@ -95,6 +112,9 @@ function vanillaExtractPlugin({
95
112
  name: PLUGIN_NAMESPACE,
96
113
  configureServer(_server) {
97
114
  server = _server;
115
+ server.watcher.on('unlink', file => {
116
+ transformedModules.delete(integration.normalizePath(file));
117
+ });
98
118
  },
99
119
  config(_userConfig, _configEnv) {
100
120
  configEnv = _configEnv;
@@ -104,7 +124,7 @@ function vanillaExtractPlugin({
104
124
  }
105
125
  };
106
126
  },
107
- async configResolved(_resolvedConfig) {
127
+ configResolved(_resolvedConfig) {
108
128
  config = _resolvedConfig;
109
129
  isBuild = config.command === 'build' && !config.build.watch;
110
130
  packageName = integration.getPackageInfo(config.root).name;
@@ -159,54 +179,71 @@ function vanillaExtractPlugin({
159
179
  var _compiler3;
160
180
  return (_compiler3 = compiler$1) === null || _compiler3 === void 0 ? void 0 : _compiler3.close();
161
181
  },
162
- async transform(code, id, options = {}) {
182
+ async transform(code, id, options) {
163
183
  const [validId] = id.split('?');
164
184
  if (!integration.cssFileFilter.test(validId)) {
165
185
  return null;
166
186
  }
167
187
  const identOption = getIdentOption();
188
+ const normalizedId = integration.normalizePath(validId);
168
189
  if (unstable_mode === 'transform') {
190
+ transformedModules.add(normalizedId);
169
191
  return integration.transform({
170
192
  source: code,
171
- filePath: integration.normalizePath(validId),
193
+ filePath: normalizedId,
172
194
  rootPath: config.root,
173
195
  packageName,
174
196
  identOption
175
197
  });
176
198
  }
177
- if (compiler$1) {
178
- const absoluteId = getAbsoluteId(validId);
179
- const {
180
- source,
181
- watchFiles
182
- } = await compiler$1.processVanillaFile(absoluteId, {
183
- outputCss: true
184
- });
185
- const result = {
186
- code: source,
187
- map: {
188
- mappings: ''
189
- }
190
- };
191
-
192
- // We don't need to watch files or invalidate modules in build mode or during SSR
193
- if (isBuild || options.ssr) {
194
- return result;
199
+ if (!compiler$1) {
200
+ return null;
201
+ }
202
+ const absoluteId = getAbsoluteId(validId);
203
+ const {
204
+ source,
205
+ watchFiles
206
+ } = await compiler$1.processVanillaFile(absoluteId, {
207
+ outputCss: true
208
+ });
209
+ transformedModules.add(normalizedId);
210
+ const result = {
211
+ code: source,
212
+ map: {
213
+ mappings: ''
195
214
  }
196
- for (const file of watchFiles) {
197
- if (!file.includes('node_modules') && integration.normalizePath(file) !== absoluteId) {
198
- this.addWatchFile(file);
199
- }
215
+ };
200
216
 
201
- // We have to invalidate the virtual module & deps, not the real one we just transformed
202
- // The deps have to be invalidated in case one of them changing was the trigger causing
203
- // the current transformation
204
- if (integration.cssFileFilter.test(file)) {
205
- invalidateModule(fileIdToVirtualId(file));
206
- }
207
- }
217
+ // We don't need to watch files or invalidate modules in build mode or during SSR
218
+ if (isBuild || options !== null && options !== void 0 && options.ssr) {
208
219
  return result;
209
220
  }
221
+ for (const file of watchFiles) {
222
+ if (!file.includes('node_modules') && integration.normalizePath(file) !== absoluteId) {
223
+ this.addWatchFile(file);
224
+ }
225
+ }
226
+ return result;
227
+ },
228
+ // The compiler's module graph is always a subset of the consuming Vite dev server's module
229
+ // graph, so this early exit will be hit for any modules that aren't related to VE modules.
230
+ async handleHotUpdate({
231
+ file,
232
+ server,
233
+ timestamp
234
+ }) {
235
+ if (!compiler$1) {
236
+ return;
237
+ }
238
+ const importerChain = await compiler$1.findImporterTree(integration.normalizePath(file), transformedModules);
239
+ if (importerChain.size === 0) {
240
+ return;
241
+ }
242
+ invalidateImporterChain({
243
+ importerChain,
244
+ server,
245
+ timestamp
246
+ });
210
247
  },
211
248
  resolveId(source) {
212
249
  var _compiler4;
@@ -41,6 +41,7 @@ function vanillaExtractPlugin({
41
41
  let compiler$1;
42
42
  let isBuild;
43
43
  const vitePromise = import('vite');
44
+ const transformedModules = new Set();
44
45
  const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
45
46
  const getAbsoluteId = filePath => {
46
47
  let resolvedId = filePath;
@@ -55,21 +56,37 @@ function vanillaExtractPlugin({
55
56
  }
56
57
  return integration.normalizePath(resolvedId);
57
58
  };
58
- function invalidateModule(absoluteId) {
59
- if (!server) return;
59
+
60
+ /**
61
+ * Custom invalidation function that takes a chain of importers to invalidate. If an importer is a
62
+ * VE module, its virtual CSS is invalidated instead. Otherwise, the module is invalidated
63
+ * normally.
64
+ */
65
+ const invalidateImporterChain = ({
66
+ importerChain,
67
+ server,
68
+ timestamp
69
+ }) => {
60
70
  const {
61
71
  moduleGraph
62
72
  } = server;
63
- const modules = moduleGraph.getModulesByFile(absoluteId);
64
- if (modules) {
65
- for (const module of modules) {
66
- moduleGraph.invalidateModule(module);
67
-
68
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
69
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
73
+ const seen = new Set();
74
+ for (const mod of importerChain) {
75
+ if (mod.id && integration.cssFileFilter.test(mod.id)) {
76
+ const virtualModules = moduleGraph.getModulesByFile(fileIdToVirtualId(mod.id));
77
+ for (const virtualModule of virtualModules ?? []) {
78
+ moduleGraph.invalidateModule(virtualModule, seen, timestamp, true);
79
+ }
80
+ } else if (mod.id) {
81
+ // `mod` is from the compiler's internal Vite server, so look up the
82
+ // corresponding module in the consuming server's graph by ID
83
+ const serverMod = moduleGraph.getModuleById(mod.id);
84
+ if (serverMod) {
85
+ moduleGraph.invalidateModule(serverMod, seen, timestamp, true);
86
+ }
70
87
  }
71
88
  }
72
- }
89
+ };
73
90
  return [{
74
91
  name: `${PLUGIN_NAMESPACE}-inline-dev-css`,
75
92
  apply: (_, {
@@ -95,6 +112,9 @@ function vanillaExtractPlugin({
95
112
  name: PLUGIN_NAMESPACE,
96
113
  configureServer(_server) {
97
114
  server = _server;
115
+ server.watcher.on('unlink', file => {
116
+ transformedModules.delete(integration.normalizePath(file));
117
+ });
98
118
  },
99
119
  config(_userConfig, _configEnv) {
100
120
  configEnv = _configEnv;
@@ -104,7 +124,7 @@ function vanillaExtractPlugin({
104
124
  }
105
125
  };
106
126
  },
107
- async configResolved(_resolvedConfig) {
127
+ configResolved(_resolvedConfig) {
108
128
  config = _resolvedConfig;
109
129
  isBuild = config.command === 'build' && !config.build.watch;
110
130
  packageName = integration.getPackageInfo(config.root).name;
@@ -159,54 +179,71 @@ function vanillaExtractPlugin({
159
179
  var _compiler3;
160
180
  return (_compiler3 = compiler$1) === null || _compiler3 === void 0 ? void 0 : _compiler3.close();
161
181
  },
162
- async transform(code, id, options = {}) {
182
+ async transform(code, id, options) {
163
183
  const [validId] = id.split('?');
164
184
  if (!integration.cssFileFilter.test(validId)) {
165
185
  return null;
166
186
  }
167
187
  const identOption = getIdentOption();
188
+ const normalizedId = integration.normalizePath(validId);
168
189
  if (unstable_mode === 'transform') {
190
+ transformedModules.add(normalizedId);
169
191
  return integration.transform({
170
192
  source: code,
171
- filePath: integration.normalizePath(validId),
193
+ filePath: normalizedId,
172
194
  rootPath: config.root,
173
195
  packageName,
174
196
  identOption
175
197
  });
176
198
  }
177
- if (compiler$1) {
178
- const absoluteId = getAbsoluteId(validId);
179
- const {
180
- source,
181
- watchFiles
182
- } = await compiler$1.processVanillaFile(absoluteId, {
183
- outputCss: true
184
- });
185
- const result = {
186
- code: source,
187
- map: {
188
- mappings: ''
189
- }
190
- };
191
-
192
- // We don't need to watch files or invalidate modules in build mode or during SSR
193
- if (isBuild || options.ssr) {
194
- return result;
199
+ if (!compiler$1) {
200
+ return null;
201
+ }
202
+ const absoluteId = getAbsoluteId(validId);
203
+ const {
204
+ source,
205
+ watchFiles
206
+ } = await compiler$1.processVanillaFile(absoluteId, {
207
+ outputCss: true
208
+ });
209
+ transformedModules.add(normalizedId);
210
+ const result = {
211
+ code: source,
212
+ map: {
213
+ mappings: ''
195
214
  }
196
- for (const file of watchFiles) {
197
- if (!file.includes('node_modules') && integration.normalizePath(file) !== absoluteId) {
198
- this.addWatchFile(file);
199
- }
215
+ };
200
216
 
201
- // We have to invalidate the virtual module & deps, not the real one we just transformed
202
- // The deps have to be invalidated in case one of them changing was the trigger causing
203
- // the current transformation
204
- if (integration.cssFileFilter.test(file)) {
205
- invalidateModule(fileIdToVirtualId(file));
206
- }
207
- }
217
+ // We don't need to watch files or invalidate modules in build mode or during SSR
218
+ if (isBuild || options !== null && options !== void 0 && options.ssr) {
208
219
  return result;
209
220
  }
221
+ for (const file of watchFiles) {
222
+ if (!file.includes('node_modules') && integration.normalizePath(file) !== absoluteId) {
223
+ this.addWatchFile(file);
224
+ }
225
+ }
226
+ return result;
227
+ },
228
+ // The compiler's module graph is always a subset of the consuming Vite dev server's module
229
+ // graph, so this early exit will be hit for any modules that aren't related to VE modules.
230
+ async handleHotUpdate({
231
+ file,
232
+ server,
233
+ timestamp
234
+ }) {
235
+ if (!compiler$1) {
236
+ return;
237
+ }
238
+ const importerChain = await compiler$1.findImporterTree(integration.normalizePath(file), transformedModules);
239
+ if (importerChain.size === 0) {
240
+ return;
241
+ }
242
+ invalidateImporterChain({
243
+ importerChain,
244
+ server,
245
+ timestamp
246
+ });
210
247
  },
211
248
  resolveId(source) {
212
249
  var _compiler4;
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
2
  import { createCompiler } from '@vanilla-extract/compiler';
3
- import { getPackageInfo, cssFileFilter, transform, normalizePath } from '@vanilla-extract/integration';
3
+ import { normalizePath, getPackageInfo, cssFileFilter, transform } from '@vanilla-extract/integration';
4
4
 
5
5
  const PLUGIN_NAMESPACE = 'vite-plugin-vanilla-extract';
6
6
  const virtualExtCss = '.vanilla.css';
@@ -33,6 +33,7 @@ function vanillaExtractPlugin({
33
33
  let compiler;
34
34
  let isBuild;
35
35
  const vitePromise = import('vite');
36
+ const transformedModules = new Set();
36
37
  const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
37
38
  const getAbsoluteId = filePath => {
38
39
  let resolvedId = filePath;
@@ -47,21 +48,37 @@ function vanillaExtractPlugin({
47
48
  }
48
49
  return normalizePath(resolvedId);
49
50
  };
50
- function invalidateModule(absoluteId) {
51
- if (!server) return;
51
+
52
+ /**
53
+ * Custom invalidation function that takes a chain of importers to invalidate. If an importer is a
54
+ * VE module, its virtual CSS is invalidated instead. Otherwise, the module is invalidated
55
+ * normally.
56
+ */
57
+ const invalidateImporterChain = ({
58
+ importerChain,
59
+ server,
60
+ timestamp
61
+ }) => {
52
62
  const {
53
63
  moduleGraph
54
64
  } = server;
55
- const modules = moduleGraph.getModulesByFile(absoluteId);
56
- if (modules) {
57
- for (const module of modules) {
58
- moduleGraph.invalidateModule(module);
59
-
60
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
61
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
65
+ const seen = new Set();
66
+ for (const mod of importerChain) {
67
+ if (mod.id && cssFileFilter.test(mod.id)) {
68
+ const virtualModules = moduleGraph.getModulesByFile(fileIdToVirtualId(mod.id));
69
+ for (const virtualModule of virtualModules ?? []) {
70
+ moduleGraph.invalidateModule(virtualModule, seen, timestamp, true);
71
+ }
72
+ } else if (mod.id) {
73
+ // `mod` is from the compiler's internal Vite server, so look up the
74
+ // corresponding module in the consuming server's graph by ID
75
+ const serverMod = moduleGraph.getModuleById(mod.id);
76
+ if (serverMod) {
77
+ moduleGraph.invalidateModule(serverMod, seen, timestamp, true);
78
+ }
62
79
  }
63
80
  }
64
- }
81
+ };
65
82
  return [{
66
83
  name: `${PLUGIN_NAMESPACE}-inline-dev-css`,
67
84
  apply: (_, {
@@ -87,6 +104,9 @@ function vanillaExtractPlugin({
87
104
  name: PLUGIN_NAMESPACE,
88
105
  configureServer(_server) {
89
106
  server = _server;
107
+ server.watcher.on('unlink', file => {
108
+ transformedModules.delete(normalizePath(file));
109
+ });
90
110
  },
91
111
  config(_userConfig, _configEnv) {
92
112
  configEnv = _configEnv;
@@ -96,7 +116,7 @@ function vanillaExtractPlugin({
96
116
  }
97
117
  };
98
118
  },
99
- async configResolved(_resolvedConfig) {
119
+ configResolved(_resolvedConfig) {
100
120
  config = _resolvedConfig;
101
121
  isBuild = config.command === 'build' && !config.build.watch;
102
122
  packageName = getPackageInfo(config.root).name;
@@ -151,54 +171,71 @@ function vanillaExtractPlugin({
151
171
  var _compiler3;
152
172
  return (_compiler3 = compiler) === null || _compiler3 === void 0 ? void 0 : _compiler3.close();
153
173
  },
154
- async transform(code, id, options = {}) {
174
+ async transform(code, id, options) {
155
175
  const [validId] = id.split('?');
156
176
  if (!cssFileFilter.test(validId)) {
157
177
  return null;
158
178
  }
159
179
  const identOption = getIdentOption();
180
+ const normalizedId = normalizePath(validId);
160
181
  if (unstable_mode === 'transform') {
182
+ transformedModules.add(normalizedId);
161
183
  return transform({
162
184
  source: code,
163
- filePath: normalizePath(validId),
185
+ filePath: normalizedId,
164
186
  rootPath: config.root,
165
187
  packageName,
166
188
  identOption
167
189
  });
168
190
  }
169
- if (compiler) {
170
- const absoluteId = getAbsoluteId(validId);
171
- const {
172
- source,
173
- watchFiles
174
- } = await compiler.processVanillaFile(absoluteId, {
175
- outputCss: true
176
- });
177
- const result = {
178
- code: source,
179
- map: {
180
- mappings: ''
181
- }
182
- };
183
-
184
- // We don't need to watch files or invalidate modules in build mode or during SSR
185
- if (isBuild || options.ssr) {
186
- return result;
191
+ if (!compiler) {
192
+ return null;
193
+ }
194
+ const absoluteId = getAbsoluteId(validId);
195
+ const {
196
+ source,
197
+ watchFiles
198
+ } = await compiler.processVanillaFile(absoluteId, {
199
+ outputCss: true
200
+ });
201
+ transformedModules.add(normalizedId);
202
+ const result = {
203
+ code: source,
204
+ map: {
205
+ mappings: ''
187
206
  }
188
- for (const file of watchFiles) {
189
- if (!file.includes('node_modules') && normalizePath(file) !== absoluteId) {
190
- this.addWatchFile(file);
191
- }
207
+ };
192
208
 
193
- // We have to invalidate the virtual module & deps, not the real one we just transformed
194
- // The deps have to be invalidated in case one of them changing was the trigger causing
195
- // the current transformation
196
- if (cssFileFilter.test(file)) {
197
- invalidateModule(fileIdToVirtualId(file));
198
- }
199
- }
209
+ // We don't need to watch files or invalidate modules in build mode or during SSR
210
+ if (isBuild || options !== null && options !== void 0 && options.ssr) {
200
211
  return result;
201
212
  }
213
+ for (const file of watchFiles) {
214
+ if (!file.includes('node_modules') && normalizePath(file) !== absoluteId) {
215
+ this.addWatchFile(file);
216
+ }
217
+ }
218
+ return result;
219
+ },
220
+ // The compiler's module graph is always a subset of the consuming Vite dev server's module
221
+ // graph, so this early exit will be hit for any modules that aren't related to VE modules.
222
+ async handleHotUpdate({
223
+ file,
224
+ server,
225
+ timestamp
226
+ }) {
227
+ if (!compiler) {
228
+ return;
229
+ }
230
+ const importerChain = await compiler.findImporterTree(normalizePath(file), transformedModules);
231
+ if (importerChain.size === 0) {
232
+ return;
233
+ }
234
+ invalidateImporterChain({
235
+ importerChain,
236
+ server,
237
+ timestamp
238
+ });
202
239
  },
203
240
  resolveId(source) {
204
241
  var _compiler4;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanilla-extract/vite-plugin",
3
- "version": "5.2.0",
3
+ "version": "5.2.1-vite-hmr-fix-20260318112727",
4
4
  "description": "Zero-runtime Stylesheets-in-TypeScript",
5
5
  "main": "dist/vanilla-extract-vite-plugin.cjs.js",
6
6
  "module": "dist/vanilla-extract-vite-plugin.esm.js",
@@ -16,8 +16,8 @@
16
16
  "author": "SEEK",
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
- "@vanilla-extract/compiler": "^0.5.0",
20
- "@vanilla-extract/integration": "^8.0.8"
19
+ "@vanilla-extract/compiler": "^0.6.0-vite-hmr-fix-20260318112727",
20
+ "@vanilla-extract/integration": "^8.0.9"
21
21
  },
22
22
  "devDependencies": {
23
23
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"