I ended up writing my own Vite plugin. If it helps anyone, I'm posting it here. You should have your manifest template file named manifest_template.xml
available in the root folder of your Vite project. The template should contain all your variables enclosed in delimiters. For exmaple:
`<SourceLocation DefaultValue="https://%{SERVER_URL}%/?version=%{VERSION_NUMBER}%" />`)
I'm using %{
and }%
respectively to denote the start and end of my variables, but you can choose your own and specify them when calling the plugin. The last piece of data that the plugin accepts is a dictionary/map of variables and actual values that those variables will be replaced with.
Here is the plugin code. Save it in a .ts
file in the root directory of your project, where vite.config.ts
is placed.
import { PluginOption } from 'vite'
const fs = require('fs-extra')
const path = require('path')
export default function OfficeManifestTransform(
capture_start: string,
capture_end: string,
replacements: Record<string, string>,
): PluginOption {
return {
name: 'office-manifest-transform',
configureServer() {
const destFile = path.resolve(__dirname, './manifest.xml')
fs.copySync(path.resolve(__dirname, './manifest_template.xml'), destFile)
// Read the file
fs.readFile(destFile, 'utf8', (err: unknown, data: string) => {
if (err) {
console.error('Manifest Transform: Error reading file:', err)
return
}
// Perform replacements
let updatedContent = data
for (const [search, replacement] of Object.entries(replacements)) {
updatedContent = updatedContent.replace(
new RegExp(capture_start + search + capture_end, 'g'),
replacement as string,
)
console.log(
'Manifest Transform: Replaced "' + capture_start + search + capture_end + '" with "' + replacement + '"',
)
}
// Write the updated content back to the file
fs.writeFile(destFile, updatedContent, 'utf8', (writeErr: unknown) => {
if (writeErr) {
console.error('Manifest Transform: Error writing file:', writeErr)
} else {
console.log('Manifest Transform: File updated successfully.')
}
})
})
},
}
}
Call it from Vite.config.ts
like this:
import OfficeManifestTransformPlugin from './vite-plugin-office-manifest-transform'
...
const replacementMap: Record<string, string> = {
VERSION_NUMBER: process.env.VITE_APP_VERSION as string,
SERVER_URL: process.env.VITE_SERVER_URL as string,
TERMS_URL: process.env.VITE_TERMS_URL as string,
PRIVACY_URL: process.env.VITE_PRIVACY_URL as string,
SUPPORT_CONTACT_URL: process.env.VITE_SUPPORT_CONTACT_URL as string,
}
return defineConfig({
...
plugins: [
mkcert(),
vue({
template: { transformAssetUrls },
}),
OfficeManifestTransformPlugin('%{', '}%', replacementMap),
...
]
...
})
Note that all my variables are defined in .env
and .env.production
files, so my manifest gets generated/updated automatically when Vite builds my project.