Le Na
Le Na

Reputation: 84

Compile assets for multiple modules with vite

I am building a website using laravel. Website has many modules, each module has its own js and scss. I want to compile all js, scss of all modules every time I type 'npm run build'.

Below is my code.

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

const modules = ['Admin', 'Blog'];

export default defineConfig({
    plugins: modules.map((module) => {
        const inputFiles = [
            ...glob.sync('./Modules/${module}/Resources/assets/js/*.js'),
            ...glob.sync('./Modules/${module}/Resources/assets/sass/*.scss'),
        ];
        
        return laravel({
            input: inputFiles,
            publicDirectory: 'public/build/',
            buildDirectory: module,
            refresh: true,
        });
    }),
});

The above code only builds the Admin module but ignores the Blog, please tell me where it went wrong. Thanks a lot.

Upvotes: 1

Views: 1360

Answers (2)

Hmerman6006
Hmerman6006

Reputation: 1911

Try build property with vite:

import path from 'path';

const inputFiles = [
    ...glob.sync('./Modules/${module}/Resources/assets/js/*.js'),
    ...glob.sync('./Modules/${module}/Resources/assets/sass/*.scss'),
];

export default defineConfig({
    plugins: [
        laravel({
            input: inputFiles,
            refresh: true,
        }),
    ],
    css: {
        preprocessorOptions: {
            scss: {
                api: 'modern-compiler', // or "modern"
                silenceDeprecations: ['mixed-decls', 'color-functions', 'global-builtin', 'import']
            }
        }
    },
    build: {
        rollupOptions: {
          input: {
            blogCss: path.resolve(__dirname, 'Modules/Blog/Resources/assets/sass/*.scss'),
            blog: path.resolve(__dirname, 'Modules/Blog/Resources/assets/js/*.js'),
            adminCss: path.resolve(__dirname, 'Modules/Admin/Resources/assets/sass/*.scss'),
            admin: path.resolve(__dirname, 'Modules/Admin/Resources/assets/js/*.js'),
          },
          output: {
            dir: 'public/build', // Output directory for all compiled files
            format: 'es', // Use ES module format
            entryFileNames: 'assets/[name].js', // Generate separate JS files for each entry point
            chunkFileNames: 'assets/[name]-[hash].js', // Hash for chunked JS files (e.g., shared code)
            assetFileNames: (assetInfo) => {
                let outputPath = '';

                // Iterate over each name in the assetInfo.names array
                if (assetInfo.names && Array.isArray(assetInfo.names)) {
                    assetInfo.names.forEach(name => {
                    if (name.endsWith('.css')) {
                        console.table({file:name});
                        // If it's a CSS file, output to the `css` directory
                        if (name.startsWith('blogCss')) {
                            outputPath = 'assets/blog-[hash].css';
                        } else if (name.startsWith('adminCss')) {
                            outputPath = 'assets/admin-[hash].css';
                        } else {
                            outputPath = 'assets/[name]-[hash].css';

                        }
                    } else {
                        // For other assets (images, fonts, etc.), output to `assets`
                        outputPath = 'assets/[name]-[hash].[ext]';
                    }
                    });
                }

                // Return the processed file path
                return outputPath;
              },
          },
        },
      },
});

Upvotes: 0

MusheAbdulHakim
MusheAbdulHakim

Reputation: 364

As of Laravel modules v11, The steps below will work.

First publish the vite-module-loader.js with

php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider" --tag="vite"

Modify your main vite.config.js file to look like this:

import {defineConfig} from 'vite';
import laravel from 'laravel-vite-plugin';
import collectModuleAssetsPaths from './vite-module-loader.js';

async function getConfig() {
    const paths = [
        'resources/css/app.css',
        'resources/js/app.js',
    ];
    const allPaths = await collectModuleAssetsPaths(paths, 'Modules');

    return defineConfig({
        plugins: [
            laravel({
                input: allPaths,
                refresh: true,
            })
        ]
    });
}

export default getConfig();

Then modify your Modules vite.config.js to look like this:

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


export const paths = [
   'Modules/ModuleName/resources/assets/sass/app.scss',
   'Modules/ModuleName/resources/assets/js/app.jsx',


];

export default defineConfig({
    build: {
        outDir: '../../public/build-ModuleName',
        emptyOutDir: true,
        manifest: true,
    },
    plugins: [
        laravel({
            publicDirectory: '../../public',
            buildDirectory: 'build-ModuleName',
            input: paths,
            refresh: true,
        }),
        react()
    ],
    server: {
        watch: {
          usePolling: true
        }
    },
});

Refer to the Documentation For more information

Make sure your server has permission to access the files in the Modules directory else, when you run npm run build, the module files won't be added to the manifest file

Upvotes: 1

Related Questions