-1

I'm working with an Office.js add-in that accepts manifest.xml file to specify add-in information. I have created a template for it named manifest_template.xml and injected some variables in it. This file needs to be copied (to the same folder with the name template.xml) and the variables need to be replaced immediately before doing npm run dev.

Is it possible to ask Vite to create a copy of my template file and then perform text transformation on it to replace those variables in dev mode?

I have achieved this in production build using a couple of Vite plugins (vite-plugin-transform and vite-plugin-cp), but they do not appear to work when I launch development server. I have tried vite-plugin-static-copy too. Some of these even appear to be triggered (e.g. the string transformation callbacks are invoked), but the actual disk file is never updated. It only works when running npm run build and not on npm run dev.

dotNET
  • 33,414
  • 24
  • 162
  • 251

1 Answers1

0

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.

dotNET
  • 33,414
  • 24
  • 162
  • 251