21

In a vue cli 3 project I want to display a version number in the webpage. The version number lies in the package.json file.

The only reference to this that I found is this link in the vue forum.

However, I can't get the proposed solution to work.

Things I tried

  1. Use webpack.definePlugin as in the linked resource:

vue.config.js

const webpack = require('webpack');

module.exports = {
  lintOnSave: true,

  configureWebpack: config => {
    return {
      plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            VERSION: require('./package.json').version,
          }
        })
      ]
    }
  },
}

Then in main.ts I read process.env, but it does not contain VERSION (I tried several variants to this, like generating a PACKAGE_JSON field like in the linked page, and generating plain values like 'foo' instead of reading from package-json). It never worked, it is like the code is being ignored. I guess the process.env is being redefined later by vue webpack stuff.

The process log in main.ts contains, however, all the stuff that process usually contains in a vue-cli project, like the mode and the VUE_APP variables defined in .env files.

  1. Try to write to process right on the configure webpack function,

like:

 configureWebpack: config => {
   process.VERSION = require('./package.json').version
 },

(to be honest I did not have much hope with this, but had to try).

  1. Tried the other solution proposed in the linked page,

like:

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.plugin('define').tap( ([options = {}]) => {
      return [{
        ...options, // these are the env variables from your .env file, if any arr defined
        VERSION: JSON.stringify(require('./package.json').version)
      }]
    })
  }
} 

But this fail silently too.

  1. Use the config.plugin('define') syntax suggested by @Oluwafemi,

like:

chainWebpack: (config) => {
  return config.plugin('define').tap(
    args => merge(args, [VERSION])
  )
},

Where VERSION is a local variable defined as:

const pkgVersion = require('./package.json').version;

const VERSION = {
  'process.env': {
    VUE_APP_VERSION: JSON.stringify(pkgVersion)
  }
}

But this is not working either.


I am re-starting the whole project everytime, so that's not the reason why the process stuff does not show up.

My vue-cli version is 3.0.1.

Community
  • 1
  • 1
Sergeon
  • 6,638
  • 2
  • 23
  • 43

8 Answers8

22

I am adding my 2 cents, as I found a shorter way and apparently the right way (https://docs.npmjs.com/misc/scripts#packagejson-vars)

Add this in your vue.config.file before the export, not inside:

process.env.VUE_APP_VERSION = process.env.npm_package_version

And voilà!

You can then use it from a component with process.env.VUE_APP_VERSION

antoni
  • 5,001
  • 1
  • 35
  • 44
  • 1
    This. Thanks! Super handy! Stay safe – utnaf Dec 31 '20 at 13:07
  • why not just use `process.env.npm_package_version` in the component? – John Mercier Jan 27 '21 at 14:26
  • This variable didn't seem to be available directly in the component. You can read more here: https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code – antoni Jan 27 '21 at 16:07
  • Hi. Sorry what is a vue.config.file -- did you mean vite config? (I am a newbie.. maybe its a Vue3 difference?) – Piotr Kula May 02 '23 at 20:52
  • Yes it's same system if you are using vite, but in this question the user is using vue-cli so there is a vue.config.js file. If you use vite, process.env variables are accessible via `import.meta.env.` instead. and you don't need the `VUE_APP_` prefix I think – antoni May 03 '23 at 16:00
7

TLDR

The following snippet in the vue.config.js file will do the trick, and will allow you to access the version of your app as APPLICATION_VERSION:

module.exports = {
  configureWebpack: config => {
    return {
      plugins: [
        new webpack.DefinePlugin({
          'APPLICATION_VERSION': JSON.stringify(require('./package.json').version),
        })
      ]
    }
  },
}

TIP:

Don't even try to add some key to process.env via webpack.definePlugin: it won't work as you probably expect.

 Why my previous efforts did not work

At the end, I solved the issue via webpack.DefinePlugin. The main issue I had is that the original solution I found was using definePlugin to write to a process.env.PACKAGE_JSON variable.

This suggests that definePlugin somehow allows to add variables to process or process.env, which is not the case. Whenever I did log process.env in the console, I didn't find the variables I was trying to push into process.env : so I though the definePlugin tech was not working.

Actually, what webpack.definePlugin does is to check for strings at compile time and change them to its value right on your code. So, if you define an ACME_VERSION variable via:

module.exports = {
  lintOnSave: true,

  configureWebpack: config => {
    return {
      plugins: [
        new webpack.DefinePlugin({
          'ACME_VERSION': 111,
        })
      ]
    }
  },
}

and then, in main.js you print console.log(ACME_VERSION), you will get 111 properly logged.

Now, however, this is just a string change at compile time. If instead of ACME_VERSION you try to define process.env.VUE_APP_ACME_VERSION...

when you log process.env the VUE_APP_ACME_VERSION key won't show up in the object. However, a raw console.log('process.env.VUE_APP_ACME_VERSION') will yield 111 as expected.

So, basically, original link and the proposed solutions were correct to some degree. However, nothing was really being added to the process object. I was logging proccess.env during my initial tries, so I didn't see anything working.

Now, however, since the process object is not being modified, I strongly suggest anyone trying to load variables to their vue app at compile time not to use it. Is misleading at best.

Community
  • 1
  • 1
Sergeon
  • 6,638
  • 2
  • 23
  • 43
7

You can simply import your package.json file and use its variables.

import { version } from "../../package.json";

console.log(version)

If you are using Webpack, you can inject the variable in the following way:

// webpack.config.js
  plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require("package.json").version)
    })
  ]

// any-module.js
console.log("Version: " + VERSION);

https://github.com/webpack/webpack/issues/237

ESP32
  • 8,089
  • 2
  • 40
  • 61
3

When building the Vue app, environment variables that don't begin with the VUE_APP_ prefix are filtered out. NODE_ENV and BASE_URL environment variables are the exception.

The above information applies when the environment variables are set prior to building the Vue app and not in this situation.

In a situation where environment variables are set during the build, it's important to look at what Vue CLI is doing.

The Vue CLI uses webpack.DefinePlugin to set environment variables using the object returned from the call to resolveClientEnv.

resolveClientEnv returns

{
   'process.env': {}
}

This means when configuring your environment variables at build time, you need to come upon a way to merge with the existing one. You need to perform a deep merge of both arrays, so that value for process.env key is an object containing keys from the resolved client environment and your keys.

chainWebpack key in the default export for vue.config.js is just about one of the ways to get this done.

The arguments passed to initialize the DefinePlugin can be merged with new environment variables that you like to configure using the underlying webpack-chain API. Here is an example:

// vue.config.js

const merge = require('deepmerge');
const pkgVersion = require('./package.json').version;

const VERSION = {
   'process.env': {
     VERSION: JSON.stringify(pkgVersion)
   }
}

module.exports = {
  chainWebpack: config => 
    config
      .plugin('define')
      .tap(
          args => merge(args, [VERSION])
      )
}
Oluwafemi Sule
  • 36,144
  • 1
  • 56
  • 81
  • This actually makes sense, because the webpack define plugin documentation (https://webpack.js.org/plugins/define-plugin/) explicitly indicates to prefer this syntax. However, it did not work :-/ – Sergeon Nov 14 '18 at 20:13
  • Tried the `deepmerge` strategy, but it didn't work. I will try in a fresh new vue-cli 3 project, to check if some changes in my project are breaking the thing out. – Sergeon Nov 15 '18 at 08:52
  • Thank you, I solved the issue at the end and you answer helped me a lot. – Sergeon Nov 15 '18 at 09:42
3

I attempted the accepted answer, and had errors. However, in the vue docs, I was able to find an answer similar (but not quite) that of @antoni's answer.

In short, just have the following in vue.config.js:

process.env.VUE_APP_VERSION = require('./package.json').version

module.exports = {
  // config
}

Docs 2020-10-27:

You can access env variables in your application code:

process.env.VUE_APP_NOT_SECRET_CODE = require('./package.json').version

During build, process.env.VUE_APP_NOT_SECRET_CODE will be replaced by the corresponding value. In the case of VUE_APP_NOT_SECRET_CODE=some_value, it will be replaced by "some_value".

In addition to VUE_APP_* variables, there are also two special variables that will always be available in your app code:

  • NODE_ENV - this will be one of "development", "production" or "test" depending on the mode the app is running in.

  • BASE_URL - this corresponds to the publicPath option in vue.config.js and is the base path your app is deployed at.

T.Woody
  • 1,142
  • 2
  • 11
  • 25
2

Your initial attempt was fine, you were just missing the JSON.stringify part:

const webpack = require('webpack');

module.exports = {    
  configureWebpack: config => {
    return {
      plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            VERSION: JSON.stringify(require('./package.json').version),
          }
        })
      ]
    }
  },
}

Edit: although the webpack docs recommend the 'process.env.VERSION' way (yellow panel):

new webpack.DefinePlugin({
  'process.env.VERSION': JSON.stringify(require('./package.json').version),
}),
yuriy636
  • 11,171
  • 5
  • 37
  • 42
  • Thank you. As you say, `JSON.stringify` was needed for the whole thing to work: otherwise, you'll get an error when trying to print it. However, it was not the reason the `VERSION` key was not showing up in my `process.env`. – Sergeon Nov 15 '18 at 09:42
2

Official solutions tend to be more reliable Modes and Environment Variables | Vue CLI

TIP

You can have computed env vars in your vue.config.js file. They still need to be prefixed with VUE_APP_. This is useful for version info

process.env.VUE_APP_VERSION = require('./package.json').version

module.exports = {
  // config
}
zheng
  • 468
  • 3
  • 8
  • 2
    I solved the problem using this solution. To anyone reading this, you may need to restart the dev server to access the variable. – Sahil Khurana May 20 '20 at 06:59
0

The answer for this on the official VueJS forum is like so:

chainWebpack: config => {
  config
    .plugin('define')
      .tap(args => {
        let v = JSON.stringify(require('./package.json').version)
        args[0]['process.env']['VERSION'] = v
        return args
      })
}

Description

Add this line to your vue.config.js file

module.exports = {
    ...
    chainWebpack: config => {
        config
            .plugin('define')
            .tap(args => {
                let v = JSON.stringify(require('./package.json').version)
                args[0]['process.env']['VERSION'] = v
                return args
            })
    }
};

Then you can use this in your vue files like so:

version: function () {
            return process.env.VERSION
        }
Bhaskar
  • 1,838
  • 1
  • 16
  • 29