I decided to bite the bullet today and upgrade from tailwind v2 to v3 for my react app. The upgrade went well, but I now have a problem where after I run "npm start", adding additional tailwind css classes in development are not picked up when the app is recompiled which I understand is the job of the JIIT engine.
I expected tailwind to detect changes and add/remove the desired classes. I tried changing the basis class from "basis-1/2" to "basis-3/4" but since I had not included the class "basis-2/5" in the initial build, the classname was present on the div after a hot reload but the class wasnt loaded in the stylesheet.
I know this is a tailwind specific issue as I investigated using chrome tools and the classname was added to the div but the value was not in the recomplied stylesheet: target css class
I thought the solution might be including all css classes while in development and purging them once in production but from researching, I think the tailwind css bundles have become too large to be fully loaded in development.
I have also tried matching different file paths in the content array in the tailwind.config.js file but that hasn't helped either.
Any help or advice on this is really apricated and happy to try people's suggestions out.
files of interest:
Package.json
{
"name": "personalreactapp",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:5000/",
"dependencies": {
"@emotion/react": "^11.6.0",
"@emotion/styled": "^11.6.0",
"@headlessui/react": "^1.4.2",
"@heroicons/react": "^1.0.5",
"@mui/icons-material": "^5.1.1",
"@mui/material": "^5.1.0",
"@mui/styles": "^5.1.0",
"@tailwindcss/forms": "^0.4.0",
"@types/js-cookie": "^3.0.1",
"axios": "^0.21.4",
"formik": "^2.2.9",
"highcharts": "^9.1.1",
"highcharts-react-official": "^3.0.0",
"history": "^5.2.0",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"merge": "^1.2.1",
"oidc-client": "^1.9.0",
"query-string": "^7.1.1",
"react": "^17.0.2",
"react-dom": "^16.0.0",
"react-hot-toast": "^2.2.0",
"react-loader-spinner": "^4.0.0",
"react-redux": "^7.2.6",
"react-router": "^6.2.1",
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "^6.0.2",
"react-scripts": "5.0.0",
"react-toastify": "^8.1.0",
"reactstrap": "^8.4.1",
"redux-devtools-extension": "^2.13.9",
"redux-logger": "^3.0.6",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"reselect": "^4.1.2",
"rimraf": "^2.6.2",
"styled-components": "^4.3.2",
"watch": "^1.0.2",
"yup": "^0.32.11"
},
"devDependencies": {
"@tailwindcss/postcss7-compat": "^2.2.17",
"ajv": "^6.9.1",
"autoprefixer": "^10.4.2",
"babel-eslint": "^10.1.0",
"cross-env": "^5.2.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^19.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-react-app": "^5.2.0",
"eslint-plugin-flowtype": "^4.6.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-only-warn": "^1.0.3",
"eslint-plugin-react": "^7.27.0",
"nan": "^2.14.1",
"postcss": "^8.4.6",
"postcss-cli": "^9.0.2",
"prettier": "^2.4.1",
"pretty-quick": "^3.1.1",
"tailwindcss": "^3.0.23",
"typescript": "^3.9.10"
},
"eslintConfig": {
"extends": "react-app"
},
"scripts": {
"start": "rimraf ./build && npm run watch:css && react-scripts start",
"build": "npm run watch:css && react-scripts build",
"build:css": "postcss src/assets/tailwind.css -o src/assets/main.css",
"watch:css": "postcss src/assets/tailwind.css -o src/assets/main.css",
"test": "cross-env CI=true react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"lint": "eslint ./src/ --max-warnings=0"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
tailwind.config.js
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}', './src/**/**/*.{js,jsx,ts,tsx}'],
theme: {
extend: {},
},
plugins: [require('@tailwindcss/forms')],
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import store from './redux/store';
import { history } from './_helpers/history';
import 'react-loader-spinner/dist/loader/css/react-spinner-loader.css';
import './assets/main.css';
const rootElement = document.getElementById('root');
ReactDOM.render(
<Router history={history}>
<Provider store={store}>
<App />
</Provider>
</Router>,
rootElement,
);
registerServiceWorker();
postcss.config
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [tailwindcss('./src/tailwind.config.js'), require('autoprefixer')],
};
assets/tailwind.css
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
After creating a new react app and comparing the apps side by side I found the problem, if anyone is having a similar problem I would recommend doing the same.
When I was using tailwind V2, I did not have a tailwind config. With the upgrade to V3 I ran the command npx tailwindcss init. The problem was I ran it inside the src folder so in the tailwind config above, the content matching paths will not work as its looking for the src folder already inside the src folder.
A second problem pointed out thanks to EdLucas in the comments is postCSS configs are no longer supported. Even with the change above, if a postCSS file is present it won't work. Deleting that file will fix the issue.
For anyone wondering the versions for tailwindCSS, postCSS and autoprefixer in package.json above are the correct versions that I used in the working solution.
I have had a similar problem and solved it by tweaking the watchers in my gulpfile.
In my gulpfile, the line that configured the watcher for my Handlebars template looked like this:
const hbsWatcher = () => watch(['*.hbs', 'partials/**/*.hbs'], hbs);
This would execute the HBS task when a change is made to my front end code. However, it did not execute the CSS task, which meant that my CSS file in which I was importing Tailwind was not re-processed properly.
I solved it by adding the CSS task into the callback of the HBS watcher:
const hbsWatcher = () => watch(['*.hbs', 'partials/**/*.hbs'], series(hbs, css));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With