heftymouse
heftymouse

Reputation: 148

How do I add a version number to a SvelteKit/Vite app?

I'm trying to create a system in my SvelteKit app where it shows you info about the current app version (ideally a Git commit hash and description) on a certain page. I tried using Vite's define feature to do this at build time but it doesn't seem to work. How do I add something like this?

Here's an example of what I tried to do:

Vite config in svelte.config.js

vite: () => ({
    define: {
        '__APP_VERSION__': JSON.stringify('testfornow')
    }
})

index.svelte:

<script lang="ts">
    const version: string = __APP_VERSION__;
</script>

<p>Current App version: {version}</p>

Upvotes: 11

Views: 6210

Answers (3)

xpuu
xpuu

Reputation: 1640

(Updated answer) In my vite.config.js I use exec to obtain information from Git. Then I use Vite config option define to do constant replacements.

import { exec } from 'child_process'
import { promisify } from 'util'

// Get current tag/commit and last commit date from git
const pexec = promisify(exec)
let [version, lastmod] = (
  await Promise.allSettled([
    pexec('git describe --tags || git rev-parse --short HEAD'),
    pexec('git log -1 --format=%cd --date=format:"%Y-%m-%d %H:%M"'),
  ])
).map(v => JSON.stringify(v.value?.stdout.trim()))

/** @type {import('vite').UserConfig} */
const config = {
  define: {
    __VERSION__: version,
    __LASTMOD__: lastmod,
  },
  ...

If you use Typescript, this needs to go to app.d.ts

// App version
declare const __VERSION__: string
// Date of last commit
declare const __LASTMOD__: string

Constants __VERSION__ and __LASTMOD__ are now available to the whole app. The only drawback is that vite-plugin-svelte complains they're not defined if you use them directly in the markup.

<script context="module" lang="ts">
   const versionInfo = `Version ${__VERSION__}, ${__LASTMOD__}`
</script>

<div>{versionInfo}</div>

Upvotes: 7

Kleber
Kleber

Reputation: 1065

You can also use the version property.

File: svelte.config.js

const config = {
    ...
    kit: {
        ...
        version: {
            name: process.env.npm_package_version
        }
    }
}

With this you are tying the versions of the app and the package.json file.

And to use it:

import { version, dev } from '$app/environment';
...
console.log(`Client version: ${version}`);

Keep in mind that with this solution, if you update your app without changing the package.json version, inconsistencies can happen (check the docs).

Upvotes: 11

urb_
urb_

Reputation: 107

This is how I managed to make it work:

  • Get the package.json data as explained in the SvelteKit FAQ, and load it as a constant in Vite config:
// svelte.config.js

import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
 
const file = fileURLToPath(new URL('package.json', import.meta.url));
const json = readFileSync(file, 'utf8');
const pkg = JSON.parse(json);

const config = {
  kit: {
    // ...
    vite: {
      define: {
        '__APP_VERSION__': JSON.stringify(pkg.version),
      }
    },
  },
  // ...
};

  • Use the variable in any svelte file:
<h2>Version: {__APP_VERSION__}</h2>

Quite similar to your example, hope it helps!

EDIT: Be aware, config changed after @sveltejs/[email protected]:

After a breaking change on @sveltejs/[email protected], Vite config must be included in its own file:

// vite.config.js

import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
 
const file = fileURLToPath(new URL('package.json', import.meta.url));
const json = readFileSync(file, 'utf8');
const pkg = JSON.parse(json);

const config = {
  define: {
    '__APP_VERSION__': JSON.stringify(pkg.version),
  }
  // ...
};

And the config.kit.vite prop must be removed from the svelte.config.js file.

Upvotes: 9

Related Questions