WEBcoast Logo

Webpack like manifest.json for Vite

For recent projects I swtiched to Vite for developping and building my frontend asset. I usually integrate the built CSS and JS files into TYPO3, which automatically creates a cache busting/versioning identifier with the files modified timestamp. However, with Symfony I prefer to use the JSON manifest approach, which results in potentially fewer cache busts.

The problem was that Symfony's JSON manifest versioning strategy requires a flat manifest file with only one level of source file to final file name mapping. Vite's built-in manifest function generates a much more complex manifest, which cause exception, when used with Symfony.

I tried to find a Vite plugin, which generates that flat manifest, but was unsuccesful. So I tried to write it myself and came up with the following solution:

import * as path from 'node:path';
import * as fs from "node:fs";

const ViteWebpackManifest = () => {
    let base = ''

    return {
        configResolved(config) {
            // Remove the leading "/" from the base URL
            base = config.base.replace(/^\//, '')
        },

        writeBundle(outputOptions, bundle) {
            const manifest = {}
            for (const [fileName, chunkInfo] of Object.entries(bundle)) {
                if (chunkInfo.type === 'asset' && chunkInfo.name) {
                    manifest[base + chunkInfo.name] = base + chunkInfo.fileName
                } else if (chunkInfo.type === 'chunk') {
                    manifest[base + chunkInfo.name + '.js'] = base + chunkInfo.fileName
                }
            }

            const manifestPath = path.resolve(outputOptions.dir, 'manifest.json')
            fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 4))
        }
    }
}

export default ViteWebpackManifest

Feel free to copy and tweak to your needs. Leave a comment, if this was useful or you have any suggestions.