@vanilla-extract/vite-plugin 3.9.4 → 4.0.0

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.
@@ -1,11 +1,10 @@
1
1
  import { Plugin } from 'vite';
2
- import { IdentifierOption, CompileOptions } from '@vanilla-extract/integration';
2
+ import { IdentifierOption } from '@vanilla-extract/integration';
3
3
 
4
4
  interface Options {
5
5
  identifiers?: IdentifierOption;
6
- emitCssInSsr?: boolean;
7
- esbuildOptions?: CompileOptions['esbuildOptions'];
6
+ unstable_mode?: 'transform' | 'emitCss';
8
7
  }
9
- declare function vanillaExtractPlugin({ identifiers, emitCssInSsr, esbuildOptions, }?: Options): Plugin;
8
+ declare function vanillaExtractPlugin({ identifiers, unstable_mode: mode, }?: Options): Plugin;
10
9
 
11
10
  export { vanillaExtractPlugin };
@@ -3,77 +3,70 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var path = require('path');
6
- var outdent = require('outdent');
7
6
  var integration = require('@vanilla-extract/integration');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
9
 
11
10
  var path__default = /*#__PURE__*/_interopDefault(path);
12
- var outdent__default = /*#__PURE__*/_interopDefault(outdent);
13
11
 
14
- // Mostly copied from vite's implementation
15
- // https://github.com/vitejs/vite/blob/efec70f816b80e55b64255b32a5f120e1cf4e4be/packages/vite/src/node/plugins/css.ts
16
- const resolvePostcssConfig = async config => {
17
- var _config$css;
18
- // inline postcss config via vite config
19
- const inlineOptions = (_config$css = config.css) === null || _config$css === void 0 ? void 0 : _config$css.postcss;
20
- const inlineOptionsIsString = typeof inlineOptions === 'string';
21
- if (inlineOptions && !inlineOptionsIsString) {
22
- const options = {
23
- ...inlineOptions
24
- };
25
- delete options.plugins;
26
- return {
27
- options,
28
- plugins: inlineOptions.plugins || []
29
- };
30
- } else {
31
- try {
32
- const searchPath = typeof inlineOptions === 'string' ? inlineOptions : config.root;
33
- const postCssConfig = await (await import('postcss-load-config')).default({}, searchPath);
34
- return {
35
- options: postCssConfig.options,
36
- plugins: postCssConfig.plugins
37
- };
38
- } catch (e) {
39
- if (!/No PostCSS Config found/.test(e.message)) {
40
- throw e;
41
- }
42
- return null;
43
- }
44
- }
45
- };
46
-
47
- const styleUpdateEvent = fileId => `vanilla-extract-style-update:${fileId}`;
48
12
  const virtualExtCss = '.vanilla.css';
49
- const virtualExtJs = '.vanilla.js';
13
+ const isVirtualId = id => id.endsWith(virtualExtCss);
14
+ const fileIdToVirtualId = id => `${id}${virtualExtCss}`;
15
+ const virtualIdToFileId = virtualId => virtualId.slice(0, -virtualExtCss.length);
50
16
  function vanillaExtractPlugin({
51
17
  identifiers,
52
- emitCssInSsr,
53
- esbuildOptions
18
+ unstable_mode: mode = 'emitCss'
54
19
  } = {}) {
55
20
  let config;
56
21
  let server;
57
- let postCssConfig;
58
- // We lazily load this utility from Vite
59
- let normalizePath;
60
- const cssMap = new Map();
61
- const hasEmitCssOverride = typeof emitCssInSsr === 'boolean';
62
- let resolvedEmitCssInSsr = hasEmitCssOverride ? emitCssInSsr : !!process.env.VITE_RSC_BUILD;
63
22
  let packageName;
64
- const getAbsoluteVirtualFileId = source => normalizePath(path__default["default"].join(config.root, source));
23
+ let compiler;
24
+ const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
25
+ const getAbsoluteId = filePath => {
26
+ let resolvedId = filePath;
27
+ if (filePath.startsWith(config.root) ||
28
+ // In monorepos the absolute path will be outside of config.root, so we check that they have the same root on the file system
29
+ path__default["default"].isAbsolute(filePath) && filePath.split(path__default["default"].sep)[1] === config.root.split(path__default["default"].sep)[1]) {
30
+ resolvedId = filePath;
31
+ } else {
32
+ // In SSR mode we can have paths like /app/styles.css.ts
33
+ resolvedId = path__default["default"].join(config.root, filePath);
34
+ }
35
+ return integration.normalizePath(resolvedId);
36
+ };
37
+ function invalidateModule(absoluteId) {
38
+ if (!server) return;
39
+ const {
40
+ moduleGraph
41
+ } = server;
42
+ const modules = moduleGraph.getModulesByFile(absoluteId);
43
+ if (modules) {
44
+ for (const module of modules) {
45
+ moduleGraph.invalidateModule(module);
46
+
47
+ // Vite uses this timestamp to add `?t=` query string automatically for HMR.
48
+ module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
49
+ }
50
+ }
51
+ }
52
+ function addWatchFiles(fromId, files) {
53
+ // We don't need to watch files in build mode
54
+ if (config.command === 'build' && !config.build.watch) {
55
+ return;
56
+ }
57
+ for (const file of files) {
58
+ if (!file.includes('node_modules') && integration.normalizePath(file) !== fromId) {
59
+ this.addWatchFile(file);
60
+ }
61
+ }
62
+ }
65
63
  return {
66
64
  name: 'vanilla-extract',
67
- enforce: 'pre',
68
65
  configureServer(_server) {
69
66
  server = _server;
70
67
  },
71
- config(_userConfig, env) {
72
- const include = env.command === 'serve' ? ['@vanilla-extract/css/injectStyles'] : [];
68
+ config() {
73
69
  return {
74
- optimizeDeps: {
75
- include
76
- },
77
70
  ssr: {
78
71
  external: ['@vanilla-extract/css', '@vanilla-extract/css/fileScope', '@vanilla-extract/css/adapter']
79
72
  }
@@ -82,151 +75,78 @@ function vanillaExtractPlugin({
82
75
  async configResolved(resolvedConfig) {
83
76
  config = resolvedConfig;
84
77
  packageName = integration.getPackageInfo(config.root).name;
85
- normalizePath = (await import('vite')).normalizePath;
86
- if (config.command === 'serve') {
87
- postCssConfig = await resolvePostcssConfig(config);
88
- }
89
- if (!hasEmitCssOverride && config.plugins.some(plugin => ['astro:build', 'remix', 'solid-start-server', 'vite-plugin-qwik', 'vite-plugin-svelte'].includes(plugin.name))) {
90
- resolvedEmitCssInSsr = true;
78
+ if (mode !== 'transform') {
79
+ var _config$inlineConfig$;
80
+ compiler = integration.createCompiler({
81
+ root: config.root,
82
+ identifiers: getIdentOption(),
83
+ cssImportSpecifier: fileIdToVirtualId,
84
+ vitePlugins: (_config$inlineConfig$ = config.inlineConfig.plugins) === null || _config$inlineConfig$ === void 0 ? void 0 : _config$inlineConfig$.flat()
85
+ // Prevent an infinite loop where the compiler creates a new instance of the plugin, which creates a new compiler etc.
86
+ .filter(plugin => typeof plugin === 'object' && plugin !== null && 'name' in plugin && plugin.name !== 'vanilla-extract')
87
+ });
91
88
  }
92
89
  },
93
- resolveId(source) {
94
- const [validId, query] = source.split('?');
95
- if (!validId.endsWith(virtualExtCss) && !validId.endsWith(virtualExtJs)) {
96
- return;
97
- }
98
-
99
- // Absolute paths seem to occur often in monorepos, where files are
100
- // imported from outside the config root.
101
- const absoluteId = source.startsWith(config.root) ? source : getAbsoluteVirtualFileId(validId);
102
-
103
- // There should always be an entry in the `cssMap` here.
104
- // The only valid scenario for a missing one is if someone had written
105
- // a file in their app using the .vanilla.js/.vanilla.css extension
106
- if (cssMap.has(absoluteId)) {
107
- // Keep the original query string for HMR.
108
- return absoluteId + (query ? `?${query}` : '');
109
- }
90
+ buildEnd() {
91
+ var _compiler;
92
+ (_compiler = compiler) === null || _compiler === void 0 ? void 0 : _compiler.close();
110
93
  },
111
- load(id) {
112
- const [validId] = id.split('?');
113
- if (!cssMap.has(validId)) {
114
- return;
115
- }
116
- const css = cssMap.get(validId);
117
- if (typeof css !== 'string') {
118
- return;
119
- }
120
- if (validId.endsWith(virtualExtCss)) {
121
- return css;
122
- }
123
- return outdent__default["default"]`
124
- import { injectStyles } from '@vanilla-extract/css/injectStyles';
125
-
126
- const inject = (css) => injectStyles({
127
- fileScope: ${JSON.stringify({
128
- filePath: validId
129
- })},
130
- css
131
- });
132
-
133
- inject(${JSON.stringify(css)});
134
-
135
- if (import.meta.hot) {
136
- import.meta.hot.on('${styleUpdateEvent(validId)}', (css) => {
137
- inject(css);
138
- });
139
- }
140
- `;
141
- },
142
- async transform(code, id, ssrParam) {
94
+ async transform(code, id) {
143
95
  const [validId] = id.split('?');
144
96
  if (!integration.cssFileFilter.test(validId)) {
145
97
  return null;
146
98
  }
147
- const identOption = identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
148
- let ssr;
149
- if (typeof ssrParam === 'boolean') {
150
- ssr = ssrParam;
151
- } else {
152
- ssr = ssrParam === null || ssrParam === void 0 ? void 0 : ssrParam.ssr;
153
- }
154
- if (ssr && !resolvedEmitCssInSsr) {
99
+ const identOption = getIdentOption();
100
+ if (mode === 'transform') {
155
101
  return integration.transform({
156
102
  source: code,
157
- filePath: normalizePath(validId),
103
+ filePath: integration.normalizePath(validId),
158
104
  rootPath: config.root,
159
105
  packageName,
160
106
  identOption
161
107
  });
162
108
  }
163
- const {
164
- source,
165
- watchFiles
166
- } = await integration.compile({
167
- filePath: validId,
168
- cwd: config.root,
169
- esbuildOptions,
170
- identOption
171
- });
172
- for (const file of watchFiles) {
173
- // In start mode, we need to prevent the file from rewatching itself.
174
- // If it's a `build --watch`, it needs to watch everything.
175
- if (config.command === 'build' || normalizePath(file) !== validId) {
176
- this.addWatchFile(file);
177
- }
178
- }
179
- const output = await integration.processVanillaFile({
180
- source,
181
- filePath: validId,
182
- identOption,
183
- serializeVirtualCssPath: async ({
184
- fileScope,
185
- source
186
- }) => {
187
- const rootRelativeId = `${fileScope.filePath}${config.command === 'build' || ssr && resolvedEmitCssInSsr ? virtualExtCss : virtualExtJs}`;
188
- const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
189
- let cssSource = source;
190
- if (postCssConfig) {
191
- const postCssResult = await (await import('postcss')).default(postCssConfig.plugins).process(source, {
192
- ...postCssConfig.options,
193
- from: undefined,
194
- map: false
195
- });
196
- cssSource = postCssResult.css;
197
- }
198
- if (server && cssMap.has(absoluteId) && cssMap.get(absoluteId) !== cssSource) {
199
- const {
200
- moduleGraph
201
- } = server;
202
- const modules = Array.from(moduleGraph.getModulesByFile(absoluteId) || []);
203
- for (const module of modules) {
204
- if (module) {
205
- moduleGraph.invalidateModule(module);
109
+ if (compiler) {
110
+ const absoluteId = getAbsoluteId(validId);
111
+ const {
112
+ source,
113
+ watchFiles
114
+ } = await compiler.processVanillaFile(absoluteId, {
115
+ outputCss: true
116
+ });
117
+ addWatchFiles.call(this, absoluteId, watchFiles);
206
118
 
207
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
208
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
209
- }
210
- }
211
- server.ws.send({
212
- type: 'custom',
213
- event: styleUpdateEvent(absoluteId),
214
- data: cssSource
215
- });
119
+ // We have to invalidate the virtual module, not the real one we just transformed
120
+ invalidateModule(fileIdToVirtualId(absoluteId));
121
+ return {
122
+ code: source,
123
+ map: {
124
+ mappings: ''
216
125
  }
217
- cssMap.set(absoluteId, cssSource);
218
-
219
- // We use the root relative id here to ensure file contents (content-hashes)
220
- // are consistent across build machines
221
- return `import "${rootRelativeId}";`;
222
- }
223
- });
224
- return {
225
- code: output,
226
- map: {
227
- mappings: ''
228
- }
229
- };
126
+ };
127
+ }
128
+ },
129
+ resolveId(source) {
130
+ var _compiler2;
131
+ const [validId, query] = source.split('?');
132
+ if (!isVirtualId(validId)) return;
133
+ const absoluteId = getAbsoluteId(validId);
134
+ if ( // We should always have CSS for a file here.
135
+ // The only valid scenario for a missing one is if someone had written
136
+ // a file in their app using the .vanilla.js/.vanilla.css extension
137
+ (_compiler2 = compiler) !== null && _compiler2 !== void 0 && _compiler2.getCssForFile(virtualIdToFileId(absoluteId))) {
138
+ // Keep the original query string for HMR.
139
+ return absoluteId + (query ? `?${query}` : '');
140
+ }
141
+ },
142
+ load(id) {
143
+ const [validId] = id.split('?');
144
+ if (!isVirtualId(validId) || !compiler) return;
145
+ const absoluteId = getAbsoluteId(validId);
146
+ const {
147
+ css
148
+ } = compiler.getCssForFile(virtualIdToFileId(absoluteId));
149
+ return css;
230
150
  }
231
151
  };
232
152
  }
@@ -3,77 +3,70 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var path = require('path');
6
- var outdent = require('outdent');
7
6
  var integration = require('@vanilla-extract/integration');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
9
 
11
10
  var path__default = /*#__PURE__*/_interopDefault(path);
12
- var outdent__default = /*#__PURE__*/_interopDefault(outdent);
13
11
 
14
- // Mostly copied from vite's implementation
15
- // https://github.com/vitejs/vite/blob/efec70f816b80e55b64255b32a5f120e1cf4e4be/packages/vite/src/node/plugins/css.ts
16
- const resolvePostcssConfig = async config => {
17
- var _config$css;
18
- // inline postcss config via vite config
19
- const inlineOptions = (_config$css = config.css) === null || _config$css === void 0 ? void 0 : _config$css.postcss;
20
- const inlineOptionsIsString = typeof inlineOptions === 'string';
21
- if (inlineOptions && !inlineOptionsIsString) {
22
- const options = {
23
- ...inlineOptions
24
- };
25
- delete options.plugins;
26
- return {
27
- options,
28
- plugins: inlineOptions.plugins || []
29
- };
30
- } else {
31
- try {
32
- const searchPath = typeof inlineOptions === 'string' ? inlineOptions : config.root;
33
- const postCssConfig = await (await import('postcss-load-config')).default({}, searchPath);
34
- return {
35
- options: postCssConfig.options,
36
- plugins: postCssConfig.plugins
37
- };
38
- } catch (e) {
39
- if (!/No PostCSS Config found/.test(e.message)) {
40
- throw e;
41
- }
42
- return null;
43
- }
44
- }
45
- };
46
-
47
- const styleUpdateEvent = fileId => `vanilla-extract-style-update:${fileId}`;
48
12
  const virtualExtCss = '.vanilla.css';
49
- const virtualExtJs = '.vanilla.js';
13
+ const isVirtualId = id => id.endsWith(virtualExtCss);
14
+ const fileIdToVirtualId = id => `${id}${virtualExtCss}`;
15
+ const virtualIdToFileId = virtualId => virtualId.slice(0, -virtualExtCss.length);
50
16
  function vanillaExtractPlugin({
51
17
  identifiers,
52
- emitCssInSsr,
53
- esbuildOptions
18
+ unstable_mode: mode = 'emitCss'
54
19
  } = {}) {
55
20
  let config;
56
21
  let server;
57
- let postCssConfig;
58
- // We lazily load this utility from Vite
59
- let normalizePath;
60
- const cssMap = new Map();
61
- const hasEmitCssOverride = typeof emitCssInSsr === 'boolean';
62
- let resolvedEmitCssInSsr = hasEmitCssOverride ? emitCssInSsr : !!process.env.VITE_RSC_BUILD;
63
22
  let packageName;
64
- const getAbsoluteVirtualFileId = source => normalizePath(path__default["default"].join(config.root, source));
23
+ let compiler;
24
+ const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
25
+ const getAbsoluteId = filePath => {
26
+ let resolvedId = filePath;
27
+ if (filePath.startsWith(config.root) ||
28
+ // In monorepos the absolute path will be outside of config.root, so we check that they have the same root on the file system
29
+ path__default["default"].isAbsolute(filePath) && filePath.split(path__default["default"].sep)[1] === config.root.split(path__default["default"].sep)[1]) {
30
+ resolvedId = filePath;
31
+ } else {
32
+ // In SSR mode we can have paths like /app/styles.css.ts
33
+ resolvedId = path__default["default"].join(config.root, filePath);
34
+ }
35
+ return integration.normalizePath(resolvedId);
36
+ };
37
+ function invalidateModule(absoluteId) {
38
+ if (!server) return;
39
+ const {
40
+ moduleGraph
41
+ } = server;
42
+ const modules = moduleGraph.getModulesByFile(absoluteId);
43
+ if (modules) {
44
+ for (const module of modules) {
45
+ moduleGraph.invalidateModule(module);
46
+
47
+ // Vite uses this timestamp to add `?t=` query string automatically for HMR.
48
+ module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
49
+ }
50
+ }
51
+ }
52
+ function addWatchFiles(fromId, files) {
53
+ // We don't need to watch files in build mode
54
+ if (config.command === 'build' && !config.build.watch) {
55
+ return;
56
+ }
57
+ for (const file of files) {
58
+ if (!file.includes('node_modules') && integration.normalizePath(file) !== fromId) {
59
+ this.addWatchFile(file);
60
+ }
61
+ }
62
+ }
65
63
  return {
66
64
  name: 'vanilla-extract',
67
- enforce: 'pre',
68
65
  configureServer(_server) {
69
66
  server = _server;
70
67
  },
71
- config(_userConfig, env) {
72
- const include = env.command === 'serve' ? ['@vanilla-extract/css/injectStyles'] : [];
68
+ config() {
73
69
  return {
74
- optimizeDeps: {
75
- include
76
- },
77
70
  ssr: {
78
71
  external: ['@vanilla-extract/css', '@vanilla-extract/css/fileScope', '@vanilla-extract/css/adapter']
79
72
  }
@@ -82,151 +75,78 @@ function vanillaExtractPlugin({
82
75
  async configResolved(resolvedConfig) {
83
76
  config = resolvedConfig;
84
77
  packageName = integration.getPackageInfo(config.root).name;
85
- normalizePath = (await import('vite')).normalizePath;
86
- if (config.command === 'serve') {
87
- postCssConfig = await resolvePostcssConfig(config);
88
- }
89
- if (!hasEmitCssOverride && config.plugins.some(plugin => ['astro:build', 'remix', 'solid-start-server', 'vite-plugin-qwik', 'vite-plugin-svelte'].includes(plugin.name))) {
90
- resolvedEmitCssInSsr = true;
78
+ if (mode !== 'transform') {
79
+ var _config$inlineConfig$;
80
+ compiler = integration.createCompiler({
81
+ root: config.root,
82
+ identifiers: getIdentOption(),
83
+ cssImportSpecifier: fileIdToVirtualId,
84
+ vitePlugins: (_config$inlineConfig$ = config.inlineConfig.plugins) === null || _config$inlineConfig$ === void 0 ? void 0 : _config$inlineConfig$.flat()
85
+ // Prevent an infinite loop where the compiler creates a new instance of the plugin, which creates a new compiler etc.
86
+ .filter(plugin => typeof plugin === 'object' && plugin !== null && 'name' in plugin && plugin.name !== 'vanilla-extract')
87
+ });
91
88
  }
92
89
  },
93
- resolveId(source) {
94
- const [validId, query] = source.split('?');
95
- if (!validId.endsWith(virtualExtCss) && !validId.endsWith(virtualExtJs)) {
96
- return;
97
- }
98
-
99
- // Absolute paths seem to occur often in monorepos, where files are
100
- // imported from outside the config root.
101
- const absoluteId = source.startsWith(config.root) ? source : getAbsoluteVirtualFileId(validId);
102
-
103
- // There should always be an entry in the `cssMap` here.
104
- // The only valid scenario for a missing one is if someone had written
105
- // a file in their app using the .vanilla.js/.vanilla.css extension
106
- if (cssMap.has(absoluteId)) {
107
- // Keep the original query string for HMR.
108
- return absoluteId + (query ? `?${query}` : '');
109
- }
90
+ buildEnd() {
91
+ var _compiler;
92
+ (_compiler = compiler) === null || _compiler === void 0 ? void 0 : _compiler.close();
110
93
  },
111
- load(id) {
112
- const [validId] = id.split('?');
113
- if (!cssMap.has(validId)) {
114
- return;
115
- }
116
- const css = cssMap.get(validId);
117
- if (typeof css !== 'string') {
118
- return;
119
- }
120
- if (validId.endsWith(virtualExtCss)) {
121
- return css;
122
- }
123
- return outdent__default["default"]`
124
- import { injectStyles } from '@vanilla-extract/css/injectStyles';
125
-
126
- const inject = (css) => injectStyles({
127
- fileScope: ${JSON.stringify({
128
- filePath: validId
129
- })},
130
- css
131
- });
132
-
133
- inject(${JSON.stringify(css)});
134
-
135
- if (import.meta.hot) {
136
- import.meta.hot.on('${styleUpdateEvent(validId)}', (css) => {
137
- inject(css);
138
- });
139
- }
140
- `;
141
- },
142
- async transform(code, id, ssrParam) {
94
+ async transform(code, id) {
143
95
  const [validId] = id.split('?');
144
96
  if (!integration.cssFileFilter.test(validId)) {
145
97
  return null;
146
98
  }
147
- const identOption = identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
148
- let ssr;
149
- if (typeof ssrParam === 'boolean') {
150
- ssr = ssrParam;
151
- } else {
152
- ssr = ssrParam === null || ssrParam === void 0 ? void 0 : ssrParam.ssr;
153
- }
154
- if (ssr && !resolvedEmitCssInSsr) {
99
+ const identOption = getIdentOption();
100
+ if (mode === 'transform') {
155
101
  return integration.transform({
156
102
  source: code,
157
- filePath: normalizePath(validId),
103
+ filePath: integration.normalizePath(validId),
158
104
  rootPath: config.root,
159
105
  packageName,
160
106
  identOption
161
107
  });
162
108
  }
163
- const {
164
- source,
165
- watchFiles
166
- } = await integration.compile({
167
- filePath: validId,
168
- cwd: config.root,
169
- esbuildOptions,
170
- identOption
171
- });
172
- for (const file of watchFiles) {
173
- // In start mode, we need to prevent the file from rewatching itself.
174
- // If it's a `build --watch`, it needs to watch everything.
175
- if (config.command === 'build' || normalizePath(file) !== validId) {
176
- this.addWatchFile(file);
177
- }
178
- }
179
- const output = await integration.processVanillaFile({
180
- source,
181
- filePath: validId,
182
- identOption,
183
- serializeVirtualCssPath: async ({
184
- fileScope,
185
- source
186
- }) => {
187
- const rootRelativeId = `${fileScope.filePath}${config.command === 'build' || ssr && resolvedEmitCssInSsr ? virtualExtCss : virtualExtJs}`;
188
- const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
189
- let cssSource = source;
190
- if (postCssConfig) {
191
- const postCssResult = await (await import('postcss')).default(postCssConfig.plugins).process(source, {
192
- ...postCssConfig.options,
193
- from: undefined,
194
- map: false
195
- });
196
- cssSource = postCssResult.css;
197
- }
198
- if (server && cssMap.has(absoluteId) && cssMap.get(absoluteId) !== cssSource) {
199
- const {
200
- moduleGraph
201
- } = server;
202
- const modules = Array.from(moduleGraph.getModulesByFile(absoluteId) || []);
203
- for (const module of modules) {
204
- if (module) {
205
- moduleGraph.invalidateModule(module);
109
+ if (compiler) {
110
+ const absoluteId = getAbsoluteId(validId);
111
+ const {
112
+ source,
113
+ watchFiles
114
+ } = await compiler.processVanillaFile(absoluteId, {
115
+ outputCss: true
116
+ });
117
+ addWatchFiles.call(this, absoluteId, watchFiles);
206
118
 
207
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
208
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
209
- }
210
- }
211
- server.ws.send({
212
- type: 'custom',
213
- event: styleUpdateEvent(absoluteId),
214
- data: cssSource
215
- });
119
+ // We have to invalidate the virtual module, not the real one we just transformed
120
+ invalidateModule(fileIdToVirtualId(absoluteId));
121
+ return {
122
+ code: source,
123
+ map: {
124
+ mappings: ''
216
125
  }
217
- cssMap.set(absoluteId, cssSource);
218
-
219
- // We use the root relative id here to ensure file contents (content-hashes)
220
- // are consistent across build machines
221
- return `import "${rootRelativeId}";`;
222
- }
223
- });
224
- return {
225
- code: output,
226
- map: {
227
- mappings: ''
228
- }
229
- };
126
+ };
127
+ }
128
+ },
129
+ resolveId(source) {
130
+ var _compiler2;
131
+ const [validId, query] = source.split('?');
132
+ if (!isVirtualId(validId)) return;
133
+ const absoluteId = getAbsoluteId(validId);
134
+ if ( // We should always have CSS for a file here.
135
+ // The only valid scenario for a missing one is if someone had written
136
+ // a file in their app using the .vanilla.js/.vanilla.css extension
137
+ (_compiler2 = compiler) !== null && _compiler2 !== void 0 && _compiler2.getCssForFile(virtualIdToFileId(absoluteId))) {
138
+ // Keep the original query string for HMR.
139
+ return absoluteId + (query ? `?${query}` : '');
140
+ }
141
+ },
142
+ load(id) {
143
+ const [validId] = id.split('?');
144
+ if (!isVirtualId(validId) || !compiler) return;
145
+ const absoluteId = getAbsoluteId(validId);
146
+ const {
147
+ css
148
+ } = compiler.getCssForFile(virtualIdToFileId(absoluteId));
149
+ return css;
230
150
  }
231
151
  };
232
152
  }
@@ -1,70 +1,64 @@
1
1
  import path from 'path';
2
- import outdent from 'outdent';
3
- import { getPackageInfo, cssFileFilter, transform, compile, processVanillaFile } from '@vanilla-extract/integration';
2
+ import { getPackageInfo, createCompiler, cssFileFilter, transform, normalizePath } from '@vanilla-extract/integration';
4
3
 
5
- // Mostly copied from vite's implementation
6
- // https://github.com/vitejs/vite/blob/efec70f816b80e55b64255b32a5f120e1cf4e4be/packages/vite/src/node/plugins/css.ts
7
- const resolvePostcssConfig = async config => {
8
- var _config$css;
9
- // inline postcss config via vite config
10
- const inlineOptions = (_config$css = config.css) === null || _config$css === void 0 ? void 0 : _config$css.postcss;
11
- const inlineOptionsIsString = typeof inlineOptions === 'string';
12
- if (inlineOptions && !inlineOptionsIsString) {
13
- const options = {
14
- ...inlineOptions
15
- };
16
- delete options.plugins;
17
- return {
18
- options,
19
- plugins: inlineOptions.plugins || []
20
- };
21
- } else {
22
- try {
23
- const searchPath = typeof inlineOptions === 'string' ? inlineOptions : config.root;
24
- const postCssConfig = await (await import('postcss-load-config')).default({}, searchPath);
25
- return {
26
- options: postCssConfig.options,
27
- plugins: postCssConfig.plugins
28
- };
29
- } catch (e) {
30
- if (!/No PostCSS Config found/.test(e.message)) {
31
- throw e;
32
- }
33
- return null;
34
- }
35
- }
36
- };
37
-
38
- const styleUpdateEvent = fileId => `vanilla-extract-style-update:${fileId}`;
39
4
  const virtualExtCss = '.vanilla.css';
40
- const virtualExtJs = '.vanilla.js';
5
+ const isVirtualId = id => id.endsWith(virtualExtCss);
6
+ const fileIdToVirtualId = id => `${id}${virtualExtCss}`;
7
+ const virtualIdToFileId = virtualId => virtualId.slice(0, -virtualExtCss.length);
41
8
  function vanillaExtractPlugin({
42
9
  identifiers,
43
- emitCssInSsr,
44
- esbuildOptions
10
+ unstable_mode: mode = 'emitCss'
45
11
  } = {}) {
46
12
  let config;
47
13
  let server;
48
- let postCssConfig;
49
- // We lazily load this utility from Vite
50
- let normalizePath;
51
- const cssMap = new Map();
52
- const hasEmitCssOverride = typeof emitCssInSsr === 'boolean';
53
- let resolvedEmitCssInSsr = hasEmitCssOverride ? emitCssInSsr : !!process.env.VITE_RSC_BUILD;
54
14
  let packageName;
55
- const getAbsoluteVirtualFileId = source => normalizePath(path.join(config.root, source));
15
+ let compiler;
16
+ const getIdentOption = () => identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
17
+ const getAbsoluteId = filePath => {
18
+ let resolvedId = filePath;
19
+ if (filePath.startsWith(config.root) ||
20
+ // In monorepos the absolute path will be outside of config.root, so we check that they have the same root on the file system
21
+ path.isAbsolute(filePath) && filePath.split(path.sep)[1] === config.root.split(path.sep)[1]) {
22
+ resolvedId = filePath;
23
+ } else {
24
+ // In SSR mode we can have paths like /app/styles.css.ts
25
+ resolvedId = path.join(config.root, filePath);
26
+ }
27
+ return normalizePath(resolvedId);
28
+ };
29
+ function invalidateModule(absoluteId) {
30
+ if (!server) return;
31
+ const {
32
+ moduleGraph
33
+ } = server;
34
+ const modules = moduleGraph.getModulesByFile(absoluteId);
35
+ if (modules) {
36
+ for (const module of modules) {
37
+ moduleGraph.invalidateModule(module);
38
+
39
+ // Vite uses this timestamp to add `?t=` query string automatically for HMR.
40
+ module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
41
+ }
42
+ }
43
+ }
44
+ function addWatchFiles(fromId, files) {
45
+ // We don't need to watch files in build mode
46
+ if (config.command === 'build' && !config.build.watch) {
47
+ return;
48
+ }
49
+ for (const file of files) {
50
+ if (!file.includes('node_modules') && normalizePath(file) !== fromId) {
51
+ this.addWatchFile(file);
52
+ }
53
+ }
54
+ }
56
55
  return {
57
56
  name: 'vanilla-extract',
58
- enforce: 'pre',
59
57
  configureServer(_server) {
60
58
  server = _server;
61
59
  },
62
- config(_userConfig, env) {
63
- const include = env.command === 'serve' ? ['@vanilla-extract/css/injectStyles'] : [];
60
+ config() {
64
61
  return {
65
- optimizeDeps: {
66
- include
67
- },
68
62
  ssr: {
69
63
  external: ['@vanilla-extract/css', '@vanilla-extract/css/fileScope', '@vanilla-extract/css/adapter']
70
64
  }
@@ -73,76 +67,29 @@ function vanillaExtractPlugin({
73
67
  async configResolved(resolvedConfig) {
74
68
  config = resolvedConfig;
75
69
  packageName = getPackageInfo(config.root).name;
76
- normalizePath = (await import('vite')).normalizePath;
77
- if (config.command === 'serve') {
78
- postCssConfig = await resolvePostcssConfig(config);
79
- }
80
- if (!hasEmitCssOverride && config.plugins.some(plugin => ['astro:build', 'remix', 'solid-start-server', 'vite-plugin-qwik', 'vite-plugin-svelte'].includes(plugin.name))) {
81
- resolvedEmitCssInSsr = true;
70
+ if (mode !== 'transform') {
71
+ var _config$inlineConfig$;
72
+ compiler = createCompiler({
73
+ root: config.root,
74
+ identifiers: getIdentOption(),
75
+ cssImportSpecifier: fileIdToVirtualId,
76
+ vitePlugins: (_config$inlineConfig$ = config.inlineConfig.plugins) === null || _config$inlineConfig$ === void 0 ? void 0 : _config$inlineConfig$.flat()
77
+ // Prevent an infinite loop where the compiler creates a new instance of the plugin, which creates a new compiler etc.
78
+ .filter(plugin => typeof plugin === 'object' && plugin !== null && 'name' in plugin && plugin.name !== 'vanilla-extract')
79
+ });
82
80
  }
83
81
  },
84
- resolveId(source) {
85
- const [validId, query] = source.split('?');
86
- if (!validId.endsWith(virtualExtCss) && !validId.endsWith(virtualExtJs)) {
87
- return;
88
- }
89
-
90
- // Absolute paths seem to occur often in monorepos, where files are
91
- // imported from outside the config root.
92
- const absoluteId = source.startsWith(config.root) ? source : getAbsoluteVirtualFileId(validId);
93
-
94
- // There should always be an entry in the `cssMap` here.
95
- // The only valid scenario for a missing one is if someone had written
96
- // a file in their app using the .vanilla.js/.vanilla.css extension
97
- if (cssMap.has(absoluteId)) {
98
- // Keep the original query string for HMR.
99
- return absoluteId + (query ? `?${query}` : '');
100
- }
82
+ buildEnd() {
83
+ var _compiler;
84
+ (_compiler = compiler) === null || _compiler === void 0 ? void 0 : _compiler.close();
101
85
  },
102
- load(id) {
103
- const [validId] = id.split('?');
104
- if (!cssMap.has(validId)) {
105
- return;
106
- }
107
- const css = cssMap.get(validId);
108
- if (typeof css !== 'string') {
109
- return;
110
- }
111
- if (validId.endsWith(virtualExtCss)) {
112
- return css;
113
- }
114
- return outdent`
115
- import { injectStyles } from '@vanilla-extract/css/injectStyles';
116
-
117
- const inject = (css) => injectStyles({
118
- fileScope: ${JSON.stringify({
119
- filePath: validId
120
- })},
121
- css
122
- });
123
-
124
- inject(${JSON.stringify(css)});
125
-
126
- if (import.meta.hot) {
127
- import.meta.hot.on('${styleUpdateEvent(validId)}', (css) => {
128
- inject(css);
129
- });
130
- }
131
- `;
132
- },
133
- async transform(code, id, ssrParam) {
86
+ async transform(code, id) {
134
87
  const [validId] = id.split('?');
135
88
  if (!cssFileFilter.test(validId)) {
136
89
  return null;
137
90
  }
138
- const identOption = identifiers ?? (config.mode === 'production' ? 'short' : 'debug');
139
- let ssr;
140
- if (typeof ssrParam === 'boolean') {
141
- ssr = ssrParam;
142
- } else {
143
- ssr = ssrParam === null || ssrParam === void 0 ? void 0 : ssrParam.ssr;
144
- }
145
- if (ssr && !resolvedEmitCssInSsr) {
91
+ const identOption = getIdentOption();
92
+ if (mode === 'transform') {
146
93
  return transform({
147
94
  source: code,
148
95
  filePath: normalizePath(validId),
@@ -151,73 +98,47 @@ function vanillaExtractPlugin({
151
98
  identOption
152
99
  });
153
100
  }
154
- const {
155
- source,
156
- watchFiles
157
- } = await compile({
158
- filePath: validId,
159
- cwd: config.root,
160
- esbuildOptions,
161
- identOption
162
- });
163
- for (const file of watchFiles) {
164
- // In start mode, we need to prevent the file from rewatching itself.
165
- // If it's a `build --watch`, it needs to watch everything.
166
- if (config.command === 'build' || normalizePath(file) !== validId) {
167
- this.addWatchFile(file);
168
- }
169
- }
170
- const output = await processVanillaFile({
171
- source,
172
- filePath: validId,
173
- identOption,
174
- serializeVirtualCssPath: async ({
175
- fileScope,
176
- source
177
- }) => {
178
- const rootRelativeId = `${fileScope.filePath}${config.command === 'build' || ssr && resolvedEmitCssInSsr ? virtualExtCss : virtualExtJs}`;
179
- const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
180
- let cssSource = source;
181
- if (postCssConfig) {
182
- const postCssResult = await (await import('postcss')).default(postCssConfig.plugins).process(source, {
183
- ...postCssConfig.options,
184
- from: undefined,
185
- map: false
186
- });
187
- cssSource = postCssResult.css;
188
- }
189
- if (server && cssMap.has(absoluteId) && cssMap.get(absoluteId) !== cssSource) {
190
- const {
191
- moduleGraph
192
- } = server;
193
- const modules = Array.from(moduleGraph.getModulesByFile(absoluteId) || []);
194
- for (const module of modules) {
195
- if (module) {
196
- moduleGraph.invalidateModule(module);
101
+ if (compiler) {
102
+ const absoluteId = getAbsoluteId(validId);
103
+ const {
104
+ source,
105
+ watchFiles
106
+ } = await compiler.processVanillaFile(absoluteId, {
107
+ outputCss: true
108
+ });
109
+ addWatchFiles.call(this, absoluteId, watchFiles);
197
110
 
198
- // Vite uses this timestamp to add `?t=` query string automatically for HMR.
199
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
200
- }
201
- }
202
- server.ws.send({
203
- type: 'custom',
204
- event: styleUpdateEvent(absoluteId),
205
- data: cssSource
206
- });
111
+ // We have to invalidate the virtual module, not the real one we just transformed
112
+ invalidateModule(fileIdToVirtualId(absoluteId));
113
+ return {
114
+ code: source,
115
+ map: {
116
+ mappings: ''
207
117
  }
208
- cssMap.set(absoluteId, cssSource);
209
-
210
- // We use the root relative id here to ensure file contents (content-hashes)
211
- // are consistent across build machines
212
- return `import "${rootRelativeId}";`;
213
- }
214
- });
215
- return {
216
- code: output,
217
- map: {
218
- mappings: ''
219
- }
220
- };
118
+ };
119
+ }
120
+ },
121
+ resolveId(source) {
122
+ var _compiler2;
123
+ const [validId, query] = source.split('?');
124
+ if (!isVirtualId(validId)) return;
125
+ const absoluteId = getAbsoluteId(validId);
126
+ if ( // We should always have CSS for a file here.
127
+ // The only valid scenario for a missing one is if someone had written
128
+ // a file in their app using the .vanilla.js/.vanilla.css extension
129
+ (_compiler2 = compiler) !== null && _compiler2 !== void 0 && _compiler2.getCssForFile(virtualIdToFileId(absoluteId))) {
130
+ // Keep the original query string for HMR.
131
+ return absoluteId + (query ? `?${query}` : '');
132
+ }
133
+ },
134
+ load(id) {
135
+ const [validId] = id.split('?');
136
+ if (!isVirtualId(validId) || !compiler) return;
137
+ const absoluteId = getAbsoluteId(validId);
138
+ const {
139
+ css
140
+ } = compiler.getCssForFile(virtualIdToFileId(absoluteId));
141
+ return css;
221
142
  }
222
143
  };
223
144
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanilla-extract/vite-plugin",
3
- "version": "3.9.4",
3
+ "version": "4.0.0",
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",
@@ -15,15 +15,12 @@
15
15
  "author": "SEEK",
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
- "@vanilla-extract/integration": "^6.2.5",
19
- "outdent": "^0.8.0",
20
- "postcss": "^8.3.6",
21
- "postcss-load-config": "^4.0.1"
18
+ "@vanilla-extract/integration": "^6.4.0"
22
19
  },
23
20
  "devDependencies": {
24
- "vite": "npm:vite@^2.7.0"
21
+ "vite": "npm:vite@^5.0.11"
25
22
  },
26
23
  "peerDependencies": {
27
- "vite": "^2.2.3 || ^3.0.0 || ^4.0.3 || ^5.0.0"
24
+ "vite": "^4.0.3 || ^5.0.0"
28
25
  }
29
26
  }