Showing the application version in a Vite-based Vue.js app

This article shows how to set the version of a Vite-based Vue.js app automatically at build time, using a Docker build argument fed by an environment variable provided by CI/CD, such as the Git tag being built.

It is tempting to read the version from the version field of package.json instead, since it is already there. This only works for Node.js projects, though, so the same approach could not be reused for an application written in another language. Relying on a Git tag also means a release does not require cloning the repository and bumping a file locally: it is often just as easy to create the tag from the GitLab UI directly.

The Dockerfile

A build argument is declared with ARG, and made available to the build steps that follow it in the same stage:

 FROM node:24 AS build-stage
 WORKDIR /app
 COPY package*.json ./
 RUN npm install
 COPY . .

+ARG APP_VERSION=dev
+ENV VITE_APP_VERSION=$APP_VERSION
+
 RUN npm run build

ARG alone is not enough, because Vite only exposes environment variables prefixed with VITE_ to client code, and a build argument is not automatically an environment variable to begin with. The ENV line does both jobs at once: it turns the build argument into an environment variable, under the name Vite expects, before npm run build runs.

The default, dev, is used whenever the image is built without specifying a version, for instance during local development.

Passing the version at build time

To set the version explicitly, --build-arg is passed to docker build, with its value taken from a variable the CI/CD platform already provides. On GitLab CI/CD, $CI_COMMIT_TAG holds the tag being built:

docker build --build-arg APP_VERSION=$CI_COMMIT_TAG .

This is only set when the pipeline is triggered by a tag, so it fits a job that runs on tagged releases. Any other variable works equally well, such as a commit SHA for untagged builds.

Reading it in the app

With the environment variable set at build time, the version is read like any other Vite environment variable, import.meta.env.VITE_APP_VERSION, directly where it is needed, for instance in an about page. Because it is undefined when the app is run directly with npm run dev, outside of the Docker build, a fallback is worth keeping:

<template>
  <p>Version: {{ version }}</p>
</template>

<script setup lang="ts">
const version: string = import.meta.env.VITE_APP_VERSION || "dev"
</script>

Verifying the result

Building the image with an explicit version and inspecting the built files confirms that the value has been substituted, and not left as a reference to be resolved later:

docker build --build-arg APP_VERSION=v1.2.3-abc1234 -t my-app .
docker run --rm my-app grep -l v1.2.3-abc1234 /usr/share/nginx/html/assets/*.js

This prints the name of the bundled file containing the version, the same way any other build-time constant would be inlined by Vite.