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