vite
vite copied to clipboard
Slow HMR due to tailwind jit
Describe the bug
I'm using the new @vitejs/plugin-react-swc
and hooking up HMR.
I've created a new project within a large monorepo. I'm using tailwind, and the tailwind purge rules apply to the entire monorepo.
HMR is working, but I'm seeing that every time I reload a component, the file that is importing tailwind is also rebuilding. Because of the monorepo size, the tailwind part is taking 4s.
The component doesn't reload until the tailwind part has recompiled. I'm wondering if it should maybe separate the two operations into two hmr events rather than trying to reload both in one transaction?
https://stackblitz.com/edit/vite-react-tailwind-pfgspw?file=src%2FApp.jsx,src%2FExample.jsx
Reproduction
https://stackblitz.com/edit/vite-react-tailwind-pfgspw?file=src%2FApp.jsx,src%2FExample.jsx
Steps to reproduce
Edit example.jsx and change the contents. While there is no tailwind affecting stuff in this component, it will still trigger an HMR of the tailwind CSS file.
System Info
System:
OS: Linux 5.15 Ubuntu 20.04.5 LTS (Focal Fossa)
CPU: (16) x64 AMD Ryzen 7 PRO 5850U with Radeon Graphics
Memory: 6.86 GB / 15.62 GB
Container: Yes
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 16.15.1 - ~/.nvm/versions/node/v16.15.1/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v16.15.1/bin/yarn
npm: 8.17.0 - ~/.nvm/versions/node/v16.15.1/bin/npm
Browsers:
Chrome: 108.0.5359.71
Firefox: 108.0.1
npmPackages:
@vitejs/plugin-react: ^3.0.1 => 3.0.1
@vitejs/plugin-react-refresh: ^1.3.6 => 1.3.6
@vitejs/plugin-react-swc: ^3 => 3.0.1
vite: ^4.0.4 => 4.0.4
Used Package Manager
yarn
Logs
Click to expand!
vite:hmr [file change] src/components/dashboard/index.tsx +7s
3:47:34 PM [vite] hmr update /src/components/dashboard/index.tsx, /src/base.css
vite:load 0.44ms [fs] /src/components/dashboard/index.tsx +6s
vite:import-analysis /node_modules/.vite/deps/react_jsx-dev-runtime.js?v=31713b38 needs interop +6s
vite:hmr [self-accepts] src/components/dashboard/index.tsx +19ms
vite:import-analysis 2.96ms [2 imports rewritten] src/components/dashboard/index.tsx +2ms
vite:transform 4.39ms /src/components/dashboard/index.tsx +6s
vite:time 7.06ms /src/components/dashboard/index.tsx +5s
vite:cache [memory] /node_modules/.vite/deps/react_jsx-dev-runtime.js?v=31713b38 +6s
vite:cache [memory] /@react-refresh +0ms
vite:load 0.82ms [fs] /src/base.css +8ms
vite:hmr [self-accepts] src/base.css +4s
vite:import-analysis 0.49ms [0 imports rewritten] src/base.css +4s
vite:transform 3793.11ms /src/base.css +4s
vite:time 3795.40ms /src/base.css +4s
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
I think this is mostly caused by a perf regression in tailwind, fixed in insiders by https://github.com/tailwindlabs/tailwindcss/pull/10234
However, even with that fix, the HMR time seems quite high.
Hi! This is "normal" to have an HMR of tailwind for every file matched by Tailwind content. This is because Tailwind is not build for this kind of devtooling. This is one of the motivation behind UnoCSS (and my personal implementation).
How big is your project? I've worked on project with recent version of Tailwind (3.2) and hundred of components without seeing any perf issue.
My tailwind/vite setup had 2-4sec hot reload time. Fixed it by changing double asterisk into single inside tailwind config content selector.
This was slow:
'./src/**/*.{vue,js,ts,jsx,tsx}',
This is instant:
'./src/*/*.{vue,js,ts,jsx,tsx}',
My tailwind/vite setup had 2-4sec hot reload time. Fixed it by changing double asterisk into single inside tailwind config content selector.
This was slow:
'./src/**/*.{vue,js,ts,jsx,tsx}',
This is instant:
'./src/*/*.{vue,js,ts,jsx,tsx}',
That resolved my headache, thanks a lot!! As others have stated in comments below, ** -> * makes it so that any files with depth > 2 will not be scanned! So this is hardly a real fix.
I solved it be removing the statement for .js files, as I didn't need them to be watched. So the proposed solution has led me to a solution, but isn't a "real" solution.
Using one start means you're only scanning folder with depth 1, this is not a real fix. Not scanning all JS files can be a solution, but you need to be sure you're not putting className in these files
@Aeonian9 @chrismcv how many files and LOC is your project? Are you using Tailwind JIT? Is running only Tailwind CSS via the CLI gives the same timing updates?
I'm seeing same thing even after https://github.com/tailwindlabs/tailwindcss/pull/10234 which helped a lot (I'm using version 3.2.6), especially when running vite inside docker container on macOS as a host where I'm getting ~15 seconds long HMRs. Once I remove Tailwind import, HRM becomes instant.
I meet this problem and I solved it by setting more precise matching rules.
module.exports = {
content: ['./*.html', './src/**/*.{js,jsx,ts,tsx}']
}
My tailwind/vite setup had 2-4sec hot reload time. Fixed it by changing double asterisk into single inside tailwind config content selector.
This was slow:
'./src/**/*.{vue,js,ts,jsx,tsx}',
This is instant:
'./src/*/*.{vue,js,ts,jsx,tsx}',
Your answer helped me a lot, thanks!
Hey, reminder that this is a dangerous fix, because any file with depth > 2 will not be scanned
@ArnaudBarre do you think that there is something Vite could do to help here? If not, I think we could close this PR in favor of Tailwind reviewing if they could change something on their side to better integrate with Vite, no?
Yeah I still don't have a repro. Personally I worked on a project with hundred of files in Tailwind globs (tens of thousand of lines in total) and HMR was still largely subsecond for CSS (mac intel).
The example is also using scss for @tailwind
which could be the bottleneck (not the in stackblitz link for me).
Plus I fixed the double HMR log in Vite 4.
Even if I think Tailwind could do a lot better in perf with an API a lot more friendly for dev server, I'm still to be proven that they are the issue in slow apps and not a Babel plugin or a CSS transformer