Login/Register
How do I add a version number to a SvelteKit/Vite app?
Asked Answered
V

3

11

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>
Vamoose answered 19/11, 2021 at 11:52 Comment(0)
R
9

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.

Redeeming answered 10/3, 2022 at 11:43 Comment(7)
This worked as far as compilation and usage goes, but do you know how to get typescript to stop reporting that "APP_VERSION is not defined"?Motorist
Place the following comment above the line when the variable is used: <!-- svelte-ignore missing-declaration -->Vanettavang
@TomaszPlonka Yes, this is what I do too for now.Redeeming
Hm, that didn't work for me for some reason. But you did point me in the right direction, so I instead assigned __APP_VERSION__ to another component-local variable with // @ts-ignore above it, and that did the trick 👍Motorist
@DigitalNinja There's a note in the define section of the vite config object documentation that suggests to "... add ... type declarations in the env.d.ts or vite-env.d.ts file to get type checks and Intellisense." e.g. declare const __APP_VERSION__: stringWorkbag
Note that the keys of define are replaced in the code directly with their value. If it has a string value and you try to assign it to a variable then you'll have to add quotes in your code as well, e.g. you can do const value = "__APP_VERSION__", but not const value = __APP_VERSION__ (as it will then look for variable in the local scope with a name matching the value you defined).Jaworski
For completeness, for vanilla Svelte it's {window.__APP_VERSION__}Lavona
R
11

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).

Ragtime answered 13/2, 2023 at 16:26 Comment(2)
perfect for me, and with minimum extra codeCastleman
As of Dec 2023 this should be the selected answerCircumvallate
R
9

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.

Redeeming answered 10/3, 2022 at 11:43 Comment(7)
This worked as far as compilation and usage goes, but do you know how to get typescript to stop reporting that "APP_VERSION is not defined"?Motorist
Place the following comment above the line when the variable is used: <!-- svelte-ignore missing-declaration -->Vanettavang
@TomaszPlonka Yes, this is what I do too for now.Redeeming
Hm, that didn't work for me for some reason. But you did point me in the right direction, so I instead assigned __APP_VERSION__ to another component-local variable with // @ts-ignore above it, and that did the trick 👍Motorist
@DigitalNinja There's a note in the define section of the vite config object documentation that suggests to "... add ... type declarations in the env.d.ts or vite-env.d.ts file to get type checks and Intellisense." e.g. declare const __APP_VERSION__: stringWorkbag
Note that the keys of define are replaced in the code directly with their value. If it has a string value and you try to assign it to a variable then you'll have to add quotes in your code as well, e.g. you can do const value = "__APP_VERSION__", but not const value = __APP_VERSION__ (as it will then look for variable in the local scope with a name matching the value you defined).Jaworski
For completeness, for vanilla Svelte it's {window.__APP_VERSION__}Lavona
I
7

(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>
Infighting answered 22/11, 2021 at 16:34 Comment(2)
Can you add an example of how to actually use __VERSION__ inside a Svelte component? As it stands, your answer is only halfway there.Ayurveda
@NatoBoram you can use it like this: const version = __VERSION__;.Reverberate

© 2022 - 2024 — McMap. All rights reserved.