Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vitePreprocess does not reload postcss.config after full vite restart #848

Closed
benjaminpreiss opened this issue Jan 29, 2024 · 14 comments
Closed
Labels
bug Something isn't working vite

Comments

@benjaminpreiss
Copy link

Describe the bug

vite-preprocess does not reevaluate the contents of postcss.config after a full vite server restart.

That means I am logging something in postcss.config.js.
When I trigger a full vite server restart via vite-plugin-restart this is not logged again, which tells me that the postcss config code is not reloaded.

Reproduction URL

https://github.com/frontline-hq/tailwind-dynamic-safelist

Reproduction

Then (requires node >= v18.13):

  • npm install -g pnpm
  • pnpm i
  • pnpm dev

Then you will see a log in the console, after the server starts:

loading postcss config...

If you now edit any .svelte file in the /routes folder, you will see that the vite server is restarted in the console (I do this with the vite plugin vite-plugin-restart)

Logs

No response

System Info

System:
    OS: macOS 12.3
    CPU: (10) arm64 Apple M1 Max
    Memory: 85.88 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.17.1/bin/yarn
    npm: 9.6.7 - ~/.nvm/versions/node/v18.17.1/bin/npm
    pnpm: 8.8.0 - ~/.nvm/versions/node/v18.17.1/bin/pnpm
    bun: 1.0.15 - ~/.bun/bin/bun
  Browsers:
    Brave Browser: 119.1.60.118
    Safari: 15.4
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.1.1 
    @sveltejs/kit: ^2.0.0 => 2.4.3 
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.0.1 
    svelte: ^4.2.7 => 4.2.9 
    vite: ^5.0.3 => 5.0.12
@benjaminpreiss benjaminpreiss added bug Something isn't working triage Awaiting triage by a project member labels Jan 29, 2024
@benjaminpreiss
Copy link
Author

Not even dependency re-optimization forces a postcss reload: https://github.com/frontline-hq/tailwind-dynamic-safelist/blob/main/getSafelist.js#L53

@dominikg
Copy link
Member

please try using restart instead of reload here: https://github.com/frontline-hq/tailwind-dynamic-safelist/blob/main/vite.config.ts#L8

@benjaminpreiss
Copy link
Author

benjaminpreiss commented Jan 29, 2024

thanks for the quick reply. I did check both restart and reload just now. Neither lead to the desired outcome.

I did check quickly by putting together a vite plugin a là:

() =>({
    name: "log-postcss",
    enforce: "pre",
    resolveId(id: string) {
        if(id.includes("postcss.config")) console.log(id)
    }
})

The postcss.config file is not processed by vite (as one can tell by checking the console logs). I wonder how I could tell vitePreprocess to "reload" postcss then?

@dominikg
Copy link
Member

vite-plugin-svelte gets recreated when the vite devserver is restarted, that causes svelte.config.js to be loaded again at which point vitePreprocess() is executed again, returning a new style preprocessor built on vite's own export for preprocessCSS.

It is possible that something in vite (or maybe even postcss-load-config?) still caches the old postcss config and returns it without reading the file again.
I'm not sure vite-plugin-svelte can do anything different here as we are not running postcss or load the config.

the postcss config itself would not go through resolveId as it isn't part of the users application (unless you import it yourself somewhere, which would however not influence postcss processing of your code).

cc @bluwy

@benjaminpreiss
Copy link
Author

Ah, yes that might be it - maybe resetting the node require cache for postcss.config.js:

delete require.cache[require.resolve('./postcss.config.js')] ?

@dominikg
Copy link
Member

dominikg commented Jan 29, 2024

btw. vite exposes server.watcher to plugins, so you would be able to implement your dynamic safelist as a vite plugin without a need for parcel watcher or jiti.

Ultimately i'd recommend against this approach though as you'll have a hard time tracking the content of the final safelist and you may end up with larger output as a result (apart from a lot of extra processing).

Clearing the require cache probably won't help, but you should be able to test this by adding that line before vitePreprocess() in svelte config. It really depends on where the postcss config is loaded and how it is cached.

@dominikg
Copy link
Member

dominikg commented Jan 29, 2024

One idea i have is that you could try to import the postcss config into your vite config instead. That gets bundled and reloaded correctly...

bonus point: postcss.config.js can be esm

//postcss.config.js
import autoprefixer from 'autoprefixer';
export default {
  plugins:[autoprefixer]
}
//vite.config.js
import postcss from './postcss.config.js';
import defineConfig from 'vite';
export default defineConfig({
  css:{postcss} 
})

vite then passes postcss config along and postcss does not try to read it again itself (at least according to the docs). Some limitations might apply in terms of what you can do in postcss config, eg plugins has to be an array to be set inline in vite config https://vitejs.dev/config/shared-options.html#css-postcss

@dominikg
Copy link
Member

@dominikg dominikg added vite and removed triage Awaiting triage by a project member labels Jan 29, 2024
@dominikg
Copy link
Member

filed vitejs/vite#15745

@benjaminpreiss
Copy link
Author

btw. vite exposes server.watcher to plugins, so you would be able to implement your dynamic safelist as a vite plugin without a need for parcel watcher or jiti.

Oh yes! Thanks for the tip 🔥

Ultimately i'd recommend against this approach though as you'll have a hard time tracking the content of the final safelist and you may end up with larger output as a result (apart from a lot of extra processing).

What do you mean by that? My approach in general of generating the dynamic safelist? Or using the watcher that is exposed by vite? AFAIK it is the only way to generate such a dynamic safelist without running into double build problems...

@benjaminpreiss
Copy link
Author

benjaminpreiss commented Jan 30, 2024

vite then passes postcss config along and postcss does not try to read it again itself (at least according to the docs). Some limitations might apply in terms of what you can do in postcss config, eg plugins has to be an array to be set inline in vite config https://vitejs.dev/config/shared-options.html#css-postcss

That might indeed be worth a try - I just think it would be great if the postcss.config.js would also be watched (like tailwind does with their config...) and not only read once

Also, if I try your solution, that means that a developer needs to do more to setup my dynamic safelisting

@dominikg
Copy link
Member

btw. vite exposes server.watcher to plugins, so you would be able to implement your dynamic safelist as a vite plugin without a need for parcel watcher or jiti.

Oh yes! Thanks for the tip 🔥

Ultimately i'd recommend against this approach though as you'll have a hard time tracking the content of the final safelist and you may end up with larger output as a result (apart from a lot of extra processing).

What do you mean by that? My approach in general of generating the dynamic safelist? Or using the watcher that is exposed by vite? AFAIK it is the only way to generate such a dynamic safelist without running into double build problems...

the dynamic safelist in general, at least if made by reading and concatenating comments in multiple source files. I can only assume you need this safelist because you construct classnames dynamically. I would suggest you limit that approach or always use the full classnames eg

const classes = someCondition ? 'bg-red-500' : 'bg-blue-500';

instead of

const classes = `bg-${someCondition ? 'red':'blue'}-500`

that way the full class should be parsable and you don't need a dynamic safelist. But this is off topic here and ofc you are free to implement such a system if you feel it makes you more productive. In my experience, this would be challenging to maintain longerm though.

@benjaminpreiss
Copy link
Author

benjaminpreiss commented Jan 30, 2024

off topic:

Ah, I see. I am building this system as part of a component library where there are certain components (like a button) that have up to 30 or more different variants.

The dynamic safelisting then parses the svelte files to determine which variants are actually used and safelists these.

That way we generate only the tailwind styles that are actually used :) which will hopefully make this component library much leaner than others regarding bundle size!

I just chose the comment analysis here as an easy to understand example...

EDIT:
I found a better way to achieve what I want: frontline-hq/tailwind-dynamic-safelist@a969acd

It adds the tailwind safelist directly to the tailwind config and utilizes rewriting the config to the filesystem to restart the server (instead of server.restart()).

@dominikg
Copy link
Member

closing here as there is an upstream PR to fix it in vite, but you'll have to wait for vite6 for it to land and there are workarounds available

vitejs/vite#15235

@dominikg dominikg closed this as not planned Won't fix, can't repro, duplicate, stale Oct 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vite
Projects
None yet
Development

No branches or pull requests

2 participants