Laravel-mix with browserSync, and tailwindCss causes infinite reloading bug

Viewed 660

In my latest project, I'm using laravel-mix with the built in browserSync, and I've added tailwindCss as a package.

This is the webpack.mix.js file:

const mix = require("laravel-mix");
require('mix-html-builder');

mix
    .setResourceRoot("../")
    .setPublicPath("public/assets")
    .browserSync({
        proxy: 'xxx',
        host: 'xxx',
        files: "public/*",
        open: false,
        reloadOnRestart: true
    })
    .html({
        htmlRoot: './resources/html/pages/*.html',
        partialRoot: './resources/html/components',
        output: '..'
    })
    .copy("resources/images", "public/assets/images")
    .js("resources/js/app.js", "js")
    .postCss(
        "resources/css/app.css",
        "css",
        [
            require("postcss-import"),
            require("tailwindcss/nesting"),
            require("tailwindcss"),
            require("autoprefixer")
        ]
    )

As soon as I comment out either the line require("tailwindcss"), or the .html({}) block, the watch command npm run watch runs nicely, if both of them are on, the mix command will run indefinitely in an endless loop (in the terminal). There are no errors, everyhting runs, it just won't stop running anymore :D

My package.json is as follows:

{
    "name": "xxx",
    "version": "1.0.0",
    "description": "## Deployment",
    "main": "index.js",
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "repository": {
        "type": "git",
        "url": "xxx"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@typescript-eslint/eslint-plugin": "^5.11.0",
        "@typescript-eslint/parser": "^5.11.0",
        "alpinejs": "^3.8.1",
        "autoprefixer": "^10.4.2",
        "browser-sync": "^2.27.7",
        "browser-sync-webpack-plugin": "^2.3.0",
        "eslint": "^8.9.0",
        "eslint-plugin-import": "^2.25.4",
        "eslint-plugin-node": "^11.1.0",
        "filename-regex": "^2.0.1",
        "laravel-mix": "^6.0.41",
        "mix-html-builder": "^0.8.0",
        "postcss": "^8.4.6",
        "postcss-import": "^14.0.2",
        "stylelint": "^14.4.0",
        "stylelint-config-standard": "^25.0.0",
        "stylelint-order": "^5.0.0",
        "tailwindcss": "^3.0.19"
    }
}

I think I'm probably missing a simple setting somewhere, can someone point me to where this might go wrong?


The solution to this particular case:

This is my new tailwind.config.js file, after @reid-gannah posted their answer. At first my content config pointed to the end of the pipeline, due to how the project was set up initially, initiating the infinite lading bug. After changing filestructure around (and implementing mix-html-builder), I never realised Tailwind still read from the generated files instead of source. So, the config below solves my question:

module.exports = {
    mode: "jit",
    content: [
        './resources/html/pages/**/*.{html,js}',
        './resources/html/components/**/*.{html,js}',
        './resources/html/layouts/**/*.{html,js}',
    ],
    theme: {
        container: {
        },
        extend: {}
    },
    variants: {
        extend: {}
    },
};
1 Answers

Ah, I think I discovered what's going on here. Looks like it's a known issue with Webpack documented by Tailwind themselves:

If your CSS seems to be rebuilding in an infinite loop, there’s a good chance it’s because your build tool doesn’t support the glob option when registering PostCSS dependencies.

Many build tools (such as webpack) don’t support this option, and as a result we can only tell them to watch specific files or entire directories. We can’t tell webpack to only watch *.html files in a directory for example.

That means that if building your CSS causes any files in those directories to change, a rebuild will be triggered, even if the changed file doesn’t match the extension in your glob.

And here's their recommendation:

To solve this problem, use more specific paths in your content config, making sure to only include directories that won’t change when your CSS builds:

module.exports = {
  content: [
    './src/**/*.{html,js}',
    './src/pages/**/*.{html,js}',
    './src/components/**/*.{html,js}',
    './src/layouts/**/*.{html,js}',
    './src/index.html',
  ],
  // ...
}

Kind of a bummer, hopefully this helps.

Source: Tailwind CSS: Content Configuration

Related