@@ -6,6 +6,8 @@ import type {
66 ConfigEnv ,
77 ViteDevServer ,
88 Rollup ,
9+ PluginOption ,
10+ UserConfig ,
911} from 'vite' ;
1012import {
1113 cssFileFilter ,
@@ -24,6 +26,22 @@ const fileIdToVirtualId = (id: string) => `${id}${virtualExtCss}`;
2426const virtualIdToFileId = ( virtualId : string ) =>
2527 virtualId . slice ( 0 , - virtualExtCss . length ) ;
2628
29+ const removeIncompatiblePlugins = ( plugin : PluginOption ) =>
30+ typeof plugin === 'object' &&
31+ plugin !== null &&
32+ 'name' in plugin &&
33+ // Prevent an infinite loop where the compiler creates a new instance of the plugin,
34+ // which creates a new compiler, which creates a new instance of the plugin, etc.
35+ plugin . name !== 'vanilla-extract' &&
36+ // Skip Remix because it throws an error if it's not loaded with a config file.
37+ // If it _is_ loaded with a config file, it will create an infinite loop because it
38+ // also has a child compiler which uses the same mechanism to load the config file.
39+ // https://github.com/remix-run/remix/pull/7990#issuecomment-1809356626
40+ // Additionally, some internal Remix plugins rely on a `ctx` object to be initialized by
41+ // the main Remix plugin, and may not function correctly without it. To address this, we
42+ // filter out all Remix-related plugins.
43+ ! plugin . name . startsWith ( 'remix' ) ;
44+
2745interface Options {
2846 identifiers ?: IdentifierOption ;
2947 unstable_mode ?: 'transform' | 'emitCss' ;
@@ -120,39 +138,39 @@ export function vanillaExtractPlugin({
120138 // Ensure we re-use the compiler instance between builds, e.g. in watch mode
121139 if ( mode !== 'transform' && ! compiler ) {
122140 const { loadConfigFromFile } = await vitePromise ;
123- const configFile = await loadConfigFromFile (
124- {
125- command : config . command ,
126- mode : config . mode ,
127- isSsrBuild : configEnv . isSsrBuild ,
128- } ,
129- config . configFile ,
130- ) ;
141+
142+ let configForViteCompiler : UserConfig | undefined ;
143+
144+ // The user has a vite config file
145+ if ( config . configFile ) {
146+ const configFile = await loadConfigFromFile (
147+ {
148+ command : config . command ,
149+ mode : config . mode ,
150+ isSsrBuild : configEnv . isSsrBuild ,
151+ } ,
152+ config . configFile ,
153+ ) ;
154+
155+ configForViteCompiler = configFile ?. config ;
156+ }
157+ // The user is using a vite-based framework that has a custom config file
158+ else {
159+ configForViteCompiler = config . inlineConfig ;
160+ }
161+
162+ const viteConfig = {
163+ ...configForViteCompiler ,
164+ plugins : configForViteCompiler ?. plugins
165+ ?. flat ( )
166+ . filter ( removeIncompatiblePlugins ) ,
167+ } ;
131168
132169 compiler = createCompiler ( {
133170 root : config . root ,
134171 identifiers : getIdentOption ( ) ,
135172 cssImportSpecifier : fileIdToVirtualId ,
136- viteConfig : {
137- ...configFile ?. config ,
138- plugins : configFile ?. config . plugins ?. flat ( ) . filter (
139- ( plugin ) =>
140- typeof plugin === 'object' &&
141- plugin !== null &&
142- 'name' in plugin &&
143- // Prevent an infinite loop where the compiler creates a new instance of the plugin,
144- // which creates a new compiler, which creates a new instance of the plugin, etc.
145- plugin . name !== 'vanilla-extract' &&
146- // Skip Remix because it throws an error if it's not loaded with a config file.
147- // If it _is_ loaded with a config file, it will create an infinite loop because it
148- // also has a child compiler which uses the same mechanism to load the config file.
149- // https://github.com/remix-run/remix/pull/7990#issuecomment-1809356626
150- // Additionally, some internal Remix plugins rely on a `ctx` object to be initialized by
151- // the main Remix plugin, and may not function correctly without it. To address this, we
152- // filter out all Remix-related plugins.
153- ! plugin . name . startsWith ( 'remix' ) ,
154- ) ,
155- } ,
173+ viteConfig,
156174 } ) ;
157175 }
158176 } ,
0 commit comments