Running Vite – npm run dev on plain PHP project

  Kiến thức lập trình

Folder structure:

  • Root dir

    • Core

    • public

      • assets (From npm run build)

      • index.php

    • src

    • views

    • vite.config.js

On running npm run build it works fine, it builds assets like it should. But on npm run dev I am not getting any errors:

but my assets do not take any form of change when i change them in src/js or src/css etc..

I also have helper function in php

function vite_asset($path): string
{
    $manifestPath = __DIR__ . '/../public/assets/.vite/manifest.json';
    if (!file_exists($manifestPath)) {
        throw new Exception("Manifest file not found: {$manifestPath}");
    }

    $manifest = json_decode(file_get_contents($manifestPath), true);

    $key = $path;
    if (isset($manifest[$key])) {
        return $manifest[$key]['file'];
    }

    $keyWithSrc = 'src/' . $path;
    if (isset($manifest[$keyWithSrc])) {
        return '/assets/' . $manifest[$keyWithSrc]['file'];
    }

    return '/assets/' . $path;
}


// In head section for styles example -- for build it works perfectly
<link rel="stylesheet" href="<?= vite_asset('css/styles.css') ?>">

This is my vite.config.js

import { defineConfig, loadEnv } from 'vite';
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, unlinkSync } from 'fs';
import { join, resolve, relative, extname, dirname } from 'path';
import sharp from 'sharp';

export default defineConfig(({ command, mode }) => {
    const env = loadEnv(mode, process.cwd(), '');
    return {
        root: '.',
        publicDir: 'static',
        build: {
            outDir: 'public/assets',
            emptyOutDir: true,
            manifest: true,
            rollupOptions: {
                input: {
                    main: 'src/js/main.js',
                    styles: 'src/css/styles.css',
                    sassStyles: 'src/sass/main.scss',
                },
                output: {
                    entryFileNames: 'js/[name].[hash].js',
                    chunkFileNames: 'js/[name].[hash].js',
                    assetFileNames: (assetInfo) => {
                        if (/.(gif|jpe?g|png|webp|svg)$/.test(assetInfo.name)) {
                            return 'images/[name][extname]';
                        }
                        if (/.css$/.test(assetInfo.name)) {
                            return 'css/[name].[hash][extname]';
                        }
                        if (/.scss$/.test(assetInfo.name)) {
                            return 'css/[name].[hash][extname]';
                        }
                        return 'assets/[name].[hash][extname]';
                    },
                },
            },
        },
        server: {
            host: 'localhost',
            port: 3000,
            strictPort: true,
            watch: {
                include: ['src/**/*.{php,js,css,scss}'],
                exclude: ['node_modules/**']
            },
            proxy: {
                '/': {
                    target: env.APP_URL,
                    changeOrigin: true,
                    secure: false,
                    ws: true,
                },
            },
        },
        plugins: [
            {
                name: 'convert-images-to-webp',
                async closeBundle() {
                    const imageDir = resolve(__dirname, 'src/images');
                    const outputDir = resolve(__dirname, 'public/assets/images');
                    const manifestPath = resolve(__dirname, 'public/assets/.vite/', 'manifest.json');

                    if (!existsSync(outputDir)) {
                        mkdirSync(outputDir, { recursive: true });
                    }

                    const existingManifest = existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, 'utf8')) : {};
                    const manifest = { ...existingManifest };

                    const processImages = async (dir) => {
                        const files = readdirSync(dir);
                        for (const file of files) {
                            const filePath = join(dir, file);
                            const isDirectory = statSync(filePath).isDirectory();
                            if (isDirectory) {
                                await processImages(filePath);
                            } else if (!filePath.includes('/favicons/')) {
                                await processImage(filePath);
                            }
                        }
                    };

                    const processImage = async (image) => {
                        const srcPath = image;
                        const imageName = relative(imageDir, srcPath).replace(/.[^/.]+$/, '');
                        const destPath = join(outputDir, imageName + '.webp');

                        // Create directory if it doesn't exist
                        const outputDirectory = dirname(destPath);
                        if (!existsSync(outputDirectory)) {
                            mkdirSync(outputDirectory, { recursive: true });
                        }

                        const ext = extname(srcPath).toLowerCase();

                        if (!['.svg'].includes(ext)) {
                            await sharp(srcPath).webp().toFile(destPath);
                        }

                        if (['.gif', '.jpg', '.jpeg', '.png', '.webp'].includes(ext)) {
                            manifest[imageName + ext] = {
                                file: `assets/images/${imageName}.webp`,
                                src: `images/${relative(imageDir, srcPath)}`,
                            };
                        } else if (ext === '.svg') {
                            copyFileSync(srcPath, join(outputDir, relative(imageDir, srcPath)));
                            manifest[imageName + '.svg'] = {
                                file: `assets/${imageName}.svg`,
                                src: `images/${relative(imageDir, srcPath)}`,
                            };
                        }
                    };

                    await processImages(imageDir);

                    writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
                },
            },
            {
                name: 'exclude-index-htaccess',
                closeBundle() {
                    const filesToExclude = ['index.php', '.htaccess'];
                    filesToExclude.forEach((file) => {
                        const filePath = resolve(__dirname, 'public/assets', file);
                        if (existsSync(filePath)) {
                            copyFileSync(filePath, resolve(__dirname, 'public', file));
                            existsSync(filePath) && unlinkSync(filePath);
                        }
                    });
                },
            },
            {
                name: 'copy-images',
                closeBundle() {
                    const copyRecursiveSync = (src, dest) => {
                        const entries = readdirSync(src, { withFileTypes: true });
                        if (!existsSync(dest)) {
                            mkdirSync(dest, { recursive: true });
                        }
                        for (let entry of entries) {
                            const srcPath = join(src, entry.name);
                            const destPath = join(dest, entry.name);
                            if (entry.isDirectory()) {
                                copyRecursiveSync(srcPath, destPath);
                            } else {
                                const ext = extname(srcPath).toLowerCase();
                                if (['.svg'].includes(ext)) {
                                    copyFileSync(srcPath, destPath);
                                }
                            }
                        }
                    };

                    const imageDir = resolve(__dirname, 'src/images');
                    const outputDir = resolve(__dirname, 'public/assets/images');
                    if (existsSync(imageDir)) {
                        copyRecursiveSync(imageDir, outputDir);
                    }
                },
            },
            {
                name: 'copy-favicons',
                closeBundle() {
                    const copyRecursiveSync = (src, dest) => {
                        const entries = readdirSync(src, { withFileTypes: true });
                        if (!existsSync(dest)) {
                            mkdirSync(dest, { recursive: true });
                        }
                        for (let entry of entries) {
                            const srcPath = join(src, entry.name);
                            const destPath = join(dest, entry.name);
                            if (entry.isDirectory()) {
                                copyRecursiveSync(srcPath, destPath);
                            } else {
                                copyFileSync(srcPath, destPath);
                            }
                        }
                    };

                    const faviconsDir = resolve(__dirname, 'src/images/favicons');
                    const outputDir = resolve(__dirname, 'public/assets/images/favicons');
                    if (existsSync(faviconsDir)) {
                        copyRecursiveSync(faviconsDir, outputDir);
                    }
                },
            },
        ],
    };
});

Change vite.config.js server options

New contributor

Nikola Stankov is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT