cxbdia's avatar

How to load multiple files via vite config using wildcards ?

I'm currently using laravel vite with Laravel 10. I would like to include all the files in my resources/css/pages/* folder to compile separately to their respective files. I tried using a wildcard (used to work in mix) but it does not work in Vite. 

Are there other options for including all the files in a particular directory in the inputs part of the vite config ? (without manually specifying the files) ?

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    server: {
        host: '0.0.0.0'
    },
    plugins: [
        laravel({
            input: [
                'resources/css/app.scss',
                'resources/css/pages/*',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
    ],
});
1 like
4 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

Vite does not natively support wildcards for file inputs in the same way that Webpack Mix does. However, you can achieve a similar result by dynamically generating the list of files using Node.js functions. Here's how you can modify your Vite configuration to include all files in the resources/css/pages/ directory:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { readdirSync } from 'fs';
import { resolve } from 'path';

// Function to get all files from a directory
function getFilesFromDir(dir, fileTypes) {
    const filesToReturn = [];

    function walkDir(currentPath) {
        const files = readdirSync(currentPath);
        for (let i in files) {
            const curFile = resolve(currentPath, files[i]);
            if (readdirSync(curFile, { withFileTypes: true }).some(dirent => dirent.isDirectory())) {
                walkDir(curFile);
            } else {
                if (fileTypes.indexOf(curFile.split('.').pop()) !== -1) {
                    filesToReturn.push(curFile);
                }
            }
        }
    }

    walkDir(resolve(__dirname, dir));
    return filesToReturn;
}

// Get all .css and .scss files in the directory
const pageStyles = getFilesFromDir('./resources/css/pages', ['css', 'scss']);

export default defineConfig({
    server: {
        host: '0.0.0.0'
    },
    plugins: [
        laravel({
            input: [
                'resources/css/app.scss',
                ...pageStyles, // Spread the array of page styles
                'resources/js/app.js',
            ],
            refresh: true,
        }),
    ],
});

In this solution, we define a getFilesFromDir function that recursively reads a directory and returns an array of file paths that match the specified file types. We then call this function to get all .css and .scss files in the resources/css/pages directory and spread them into the input array of the Vite configuration.

This way, you don't have to manually specify each file, and any new files added to the directory will be automatically included in the build process.

pc_magas's avatar

@laryai The A.I Solution throws this error:

node:fs:1513
  const result = binding.readdir(
                         ^

Error: ENOTDIR: not a directory, scandir '/var/www/html/resources/css/fa-check.css'
    at readdirSync (node:fs:1513:26)
    at walkDir (file:///var/www/html/test.mjs:41:17)
    at getFilesFromDir (file:///var/www/html/test.mjs:51:5)
    at file:///var/www/html/test.mjs:55:20
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:120:12) {
  errno: -20,
  code: 'ENOTDIR',
  syscall: 'scandir',
  path: '/var/www/html/resources/css/my.css'
}

And a fix for it is:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

import { readdirSync,lstatSync } from 'fs';
import { resolve } from 'path';


function getFilesFromDir(dir, fileTypes) {
    const filesToReturn = [];

    function walkDir(currentPath) {

        if(lstatSync(currentPath).isFile()){
            filesToReturn.push(currentPath);
            return;
        }

        const files = readdirSync(currentPath);
        for (let i in files) {
            const curFile = resolve(currentPath, files[i]);
            if(lstatSync(curFile).isDirectory()){
                walkDir(curFile);
                continue;
            }
            filesToReturn.push(curFile);
        }
    }

    walkDir(resolve(__dirname, dir));
    return filesToReturn;
}

const pageStyles = getFilesFromDir('./resources/css', ['css', 'scss']);
const js = getFilesFromDir('./resources/js',['js']);

export default defineConfig({
    server: {
        host: '0.0.0.0'
    },
    plugins: [
        laravel({
            input: [
                'resources/css/app.scss',
                ...pageStyles, // Spread the array of page styles
               ...js,
                'resources/js/app.js',
            ],
            refresh: true,
        }),
    ],
});
gabriel2m's avatar

You can use glob: npmjs.com/package/glob

import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import { globSync } from "glob";

export default defineConfig({
    plugins: [
        laravel({
            input: globSync("resources/{css,js}/**/*.*", {
                ignore: "resources/js/bootstrap.js",
            }),
            refresh: true,
        }),
    ],
});
3 likes
abdallahalsamman's avatar

@gabriel2m thank you so much! saved me so much typing

using it like this

export default defineConfig({
    plugins: [
        laravel({
            input: globSync("resources/{css,js,plugins}/**/*.{css,js}"),
            refresh: true,
        }),
    ]
});
1 like

Please or to participate in this conversation.