252

How do I display the app version in Angular application? The version should be taken from package.json file.

{
  "name": "angular-app",
  "version": "0.0.1",
  ...
}

In Angular 1.x, I have this html:

<p><%=version %></p>

In Angular, this is not rendered as version number, but instead just printed as it is (<%=version %> instead of 0.0.1).

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
Zbynek
  • 5,673
  • 6
  • 30
  • 52
  • 1
    you need some gulp or grunt plugin, if you have a build system. there currently isn't AFIK any mechanism in Angular for this – Angular University Jan 20 '16 at 19:26
  • I use program the app in `typescript`, use `npm start` to run the compilation and `SystemJS` to set the configuration. is there a way to set version using any of these? – Zbynek Jan 20 '16 at 19:35

17 Answers17

427

If you want to use/show the version number in your angular app please do the following:

Prerequisites:

  • Angular file and folder structure created via Angular CLI

Steps for Angular 6.1 (TS 2.9+) till Angular 11

  1. In your /tsconfig.json (sometimes also necessary in /src/tsconfig.app.json) enable the following option (webpack dev server restart required afterwards):
    "compilerOptions": {
      ...
      "resolveJsonModule": true,
      ...
  1. Then in your component, for example /src/app/app.component.ts use the version info like this:
    import { version } from '../../package.json';
    ...
    export class AppComponent {
      public version: string = version;
    }

When using this code with Angular 12+ you will probably get: Error: Should not import the named export 'version' (imported as 'version') from default-exporting module (only default export is available soon). In this case please use the following code:

Steps for Angular 12+

  1. In your /tsconfig.json (sometimes also necessary in /src/tsconfig.app.json) enable the following options (webpack dev server restart required afterwards):
    "compilerOptions": {
      ...
      "resolveJsonModule": true,
      "allowSyntheticDefaultImports": true,
      ...
  1. Then in your component, for example /src/app/app.component.ts use the version info like this:
    import packageJson from '../../package.json';
    ...
    export class AppComponent {
      public version: string = packageJson.version;
    }

It's also possible to do step 2 in your environment.ts file, making the version info accessible from there.

Thx @Ionaru and @MarcoRinck for helping out.

This solution should not include the package.json contents when doing a production build - only the version number (checked w/Angular 8 and 13).

To be sure please check your generated main.#hash#.js file too!

radomeit
  • 4,399
  • 1
  • 12
  • 11
  • This solution worked brilliantly for dev builds but fails with AoT – wwarby Apr 11 '18 at 07:26
  • 24
    this works with angular 5 and aot compilation if anyone was wondering – Nikola.Lukovic May 01 '18 at 14:46
  • if someone gets error: `cannot find name 'require'` this can help: https://stackoverflow.com/a/43129815/1889607 – Vahid Jun 09 '18 at 12:10
  • 7
    Important note: **restart** your server (do ng serve or npm start again) for this to take effect! – user1884155 Apr 18 '19 at 15:46
  • 2
    I would not recommend adding Node.js typings to your Angular application, this can have unexpected side effects with functions where Node.js and browsers have different implementations, like timers and intervals. It is also possible to import json files using normal es6 syntax, see my answer. – Ionaru May 02 '19 at 08:58
  • 1
    @lonaru: This only applies to TypeScript 2.9+, am I correct? – radomeit May 02 '19 at 11:12
  • @radomeit Yes, importing JSON files requires TypeScript 2.9+. – Ionaru May 05 '19 at 10:58
  • 1
    @lonaru: I updated my answer and recommend the users to check out your answer as an alternative solution, if they are using at least TypeScript 2.9 – radomeit May 07 '19 at 12:11
  • 19
    This answer should not be accepted as it opens a security problem because you are now including your package.json in the browser bundle and everyone on the internet can now read your internal project configuration. Please edit it with the soliution by @Ionarus – Marco Rinck May 29 '19 at 14:00
  • 3
    @MarcoRinck: Thx for pointing this out. I could reproduce this issue. Don't know if it came due to an edit of the answer in the past but to make sure that no one uses the old solution anymore I edited the answer and removed the problematic require() call in it. – radomeit May 30 '19 at 19:28
  • 4
    angular 8 confirmed – vuhung3990 Aug 23 '19 at 08:15
  • 1
    If tslint complains about the import, consider adding resolveJsonModule in tsconfig.json instead of tsconfig.app.json. – AC101 Oct 16 '19 at 18:13
  • Restart which web server? My JavaScript server? HTML server? ;) – Martin Schneider Jan 31 '20 at 21:22
  • The webpack dev server - meaning the server that you start with ng serve – radomeit Feb 03 '20 at 10:42
  • 2
    Doesn't work under Angular 9: `File '[...]/package.json' is not under 'rootDir' '[...]/src'. 'rootDir' is expected to contain all source files.` – fr0 Feb 12 '20 at 20:42
  • 1
    @fr0 I don't think that is a bug in Angular, check out https://github.com/ng-packagr/ng-packagr/issues/1210 – Ionaru Feb 27 '20 at 09:12
  • 4
    Angular 9 confirmed – Mike de Klerk Apr 26 '20 at 18:52
  • 4
    Angular 10 confirmed – Raphaël Balet Aug 17 '20 at 15:59
  • 1
    This solution worked for me, but I had to add the "resolveJsonModule" property to the tsconfig.base.json to get it to work. Just adding it to tsconfig.json didn't give me what I needed. – Jadamae77 Aug 27 '20 at 17:39
  • Does this only work when using `ng serve`? or also when deploying the app for production? (nginx, or S3) – Daniel Aug 28 '20 at 15:00
  • 1
    @Puriajahanbani that's correct. As described above TypeScript 2.9 is required, which is supported only from Angular 6.1 upwards – radomeit Sep 24 '20 at 07:33
  • I had the same `rootDir` issue as @fr0 in my library. They easiest way I could find to solve it was to create a simple script to read the package.json in the library and create a json file in the `rootDir` right before building. The initial file is committed so that it can be imported within the project. – Geo242 Nov 19 '20 at 18:46
  • Similarly to others, adding "resolveJsonModule" property to the tsconfig.json didn't help, I needed to add it to tsconfig.app.json. – Budda May 13 '21 at 05:28
  • 19
    broken in angular 12 due to webpack 5 -_- – minigeek May 13 '21 at 07:39
  • 2
    Angular 11 confirmed – Edward Ramos Jul 16 '21 at 20:00
  • 2
    Anyone else getting this from the compiler: Should not import the named export 'version' (imported as 'version') from default-exporting module (only default export is available soon)? – Rafael Guimaraes Siqueira Aug 06 '21 at 20:07
  • 1
    Also getting above error on Angular 12.1 - probably due to the above mentioned webpack update- can be solved by using default import and adding `"allowSyntheticDefaultImports": true` to tsconfig.ts `CompilerOptions` but it imports whole package.json - so again SECURITY ISSUES mentioned mentioned above. Proper solution would be to have a build time script to add version number to code? – Ivan Aug 11 '21 at 08:48
  • In Angular 12 - this is what works for sure. Just add import { VERSION } from '@angular/core'; And then use VERSION.full to see full version. – sleepwalker Sep 08 '21 at 16:51
  • 7
    @sleepwalker that shows the angular version not the version in package.json – Mertus Oct 04 '21 at 20:22
  • 2
    Wonderful! Works on Angular 13.2.2. – Octave Mar 13 '22 at 16:17
  • 1
    Worked for Angular 14 SSR. – propatience Dec 15 '22 at 13:22
66

If you're using webpack or angular-cli (which uses webpack), you can just require package.json in your component and display that prop.

const { version: appVersion } = require('../../package.json')
// this loads package.json
// then you destructure that object and take out the 'version' property from it
// and finally with ': appVersion' you rename it to const appVersion

And then you have your component

@Component({
  selector: 'stack-overflow',
  templateUrl: './stack-overflow.component.html'
})
export class StackOverflowComponent {
  public appVersion

  constructor() {
    this.appVersion = appVersion
  }
}
Tr1stan
  • 2,755
  • 1
  • 26
  • 45
damirsehic
  • 1,117
  • 2
  • 12
  • 17
  • 9
    It's worth to mentioned that if someone encounter on error "Cannot find name require" after applying your solution then needs to add "node" type inside "types" property in tsconfig.app.ts file. << "types": ["node"] >>. Tested in Angular v4 – Tomasz Czechowski Jun 07 '17 at 15:15
  • @baio - I have this snippet of code running in my production apps for about a year now (running AOT in production). Can I help you debug your issue somehow? – damirsehic Oct 27 '17 at 10:57
  • 13
    Despite this post has some time I have to point out that this would potentially expose some build and development info int production builds and that is potentially harmful por a production environment. – ZetaPR Jan 25 '18 at 09:33
  • @ZetaPR exactly not recommended! – Jimmy Kane Feb 10 '18 at 20:56
  • You shouldn't put any sensitive data inside of your `package.json` @ZetaPR, that is just bad practice. – damirsehic Feb 14 '18 at 16:07
  • 12
    @DyslexicDcuk libraries with version numbers is sensitive data from a security perspective. – Rafiek Feb 23 '18 at 13:45
46

Using the tsconfig option --resolveJsonModule you can import json files in Typescript.

In the environment.ts file:

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

export const environment = {
    VERSION: version,
};

You can now use environment.VERSION in your application.

Ionaru
  • 982
  • 3
  • 13
  • 23
  • 2
    @lonaru Are any security implications when importing the package.json file. I am wondering if this in some way exposes the content of package.json? – tif May 03 '19 at 11:11
  • 4
    @tif There should be no security implications because the package.json is not fully imported. The version is the only thing that ends up in the production build. – Ionaru May 04 '19 at 17:53
  • 4
    When using this, make sure you publicly deploy only the **production** build (`ng build --prod`); "regular" builds **do** contain the whole `package.json` (verified with 11.0.5) – Janaka Bandara Mar 01 '21 at 07:41
21

Trying DyslexicDcuk's answer resulted in cannot find name require

Then, reading 'Optional Module Loading and Other Advanced Loading Scenarios' section in https://www.typescriptlang.org/docs/handbook/modules.html helped me solve this. (Mentioned by Gary here https://stackoverflow.com/a/41767479/7047595)

Use the below declaration to require package.json.

declare function require(moduleName: string): any;

const {version : appVersion} = require('path-to-package.json');
Community
  • 1
  • 1
Vamsi
  • 419
  • 4
  • 7
17

It is a good idea to declare version as environment variable So you can use it everywhere in your project. (specially in case of loading files to be cached based on version e.g. yourCustomjsonFile.json?version=1.0.0)
In order to prevent security issues (as @ZetaPR mentioned) we can use this approach (on @sgwatgit 's comment)
In short: we create a yourProjectPath\PreBuild.js file. Like this:

const path = require('path');
const colors = require('colors/safe');
const fs = require('fs');
const dada = require.resolve('./package.json');
const appVersion = require('./package.json').version;

console.log(colors.cyan('\nRunning pre-build tasks'));

const versionFilePath = path.join(__dirname + '/src/environments/version.ts');

const src = `export const version = '${appVersion}';
`;
console.log(colors.green(`Dada ${colors.yellow(dada)}`));

// ensure version module pulls value from package.json
fs.writeFile(versionFilePath, src, { flag: 'w' }, function (err) {
if (err) {
    return console.log(colors.red(err));
}

console.log(colors.green(`Updating application version         
${colors.yellow(appVersion)}`));
console.log(`${colors.green('Writing version module to 
')}${colors.yellow(versionFilePath)}\n`);
});

Above snippet will create a new file /src/environments/version.ts which contains a constant named version and set it by extracted value from package.json file.

In order to run content of PreBuild.json on build, We add this file into Package.json -> "scripts": { ... }" section like following. So we can run project using this code: npm start:

{
  "name": "YourProject",
  "version": "1.0.0",
  "license": "...",
  "scripts": {
    "ng": "...",
    "start": "node PreBuild.js & ng serve",
  },...
}

Now we can simply import version and use it wherever we want:

import { version } from '../../../../environments/version';
...
export class MyComponent{
  ...
  public versionUseCase: string = version;
}
Christophe Le Besnerais
  • 3,895
  • 3
  • 24
  • 44
Rzassar
  • 2,117
  • 1
  • 33
  • 55
  • This is good because it solves the "Should not import the named export 'version'" https://stackoverflow.com/questions/70298948/how-to-securely-import-version-from-package-json-while-respecting-error-should – David Wilton Apr 05 '22 at 03:11
11

Typescript

import { Component, OnInit } from '@angular/core';
declare var require: any;

@Component({
  selector: 'app-version',
  templateUrl: './version.component.html',
  styleUrls: ['./version.component.scss']
})
export class VersionComponent implements OnInit {
  version: string = require( '../../../../package.json').version;

  constructor() {}

  ngOnInit() {

  }
}

HTML

<div class="row">
    <p class="version">{{'general.version' | translate}}: {{version}}</p>
</div>
vrbsm
  • 1,188
  • 15
  • 22
11

Simplist solution for angular cli users.

Add declare module '*.json'; on src/typings.d.ts

And then on src/environments/environment.ts:

import * as npm from '../../package.json';

export const environment = {
  version: npm.version
};

Done :)

박관영
  • 119
  • 1
  • 4
  • 1
    You might need to add `"allowSyntheticDefaultImports": true` to your tsconfig.json depending on your Angular version. – bjornalm Jan 09 '19 at 14:45
11

In Angular 12 import { version } from '../../package.json'; gives an error:

./src/environments/environment.ts:10:13-20 - Error: Should not import the named export 'version' (imported as 'version') from default-exporting module (only default export is available soon)

To continue importing the version without the security implications of bringing the whole contents of package.json into the build, you can do:

export const environment = {
  ...
  VERSION: require('../../package.json').version,
};

From https://github.com/angular/angular-cli/issues/3770#issuecomment-269822722

If you encounter a Cannot find name 'require' error, see https://stackoverflow.com/a/43129815/418819 and https://stackoverflow.com/a/54004979/418819

Steve
  • 1,084
  • 11
  • 17
5

I have tried to solve this in a bit different way, also considering the ease of convenience and maintainability.

I have used the bash script to change the version across the whole application. The following script will ask you for the desired version number, and the same is applied throughout the application.

#!/bin/bash
set -e

# This script will be a single source of truth for changing versions in the whole app
# Right now its only changing the version in the template (e.g index.html), but we can manage
# versions in other files such as CHANGELOG etc.

PROJECT_DIR=$(pwd)
TEMPLATE_FILE="$PROJECT_DIR/src/index.html"
PACKAGE_FILE="$PROJECT_DIR/package.json"

echo ">> Change Version to"
read -p '>> Version: ' VERSION

echo
echo "  #### Changing version number to $VERSION  ####  "
echo

#change in template file (ideally footer)
sed -i '' -E "s/<p>(.*)<\/p>/<p>App version: $VERSION<\/p>/" $TEMPLATE_FILE
#change in package.json
sed -i '' -E "s/\"version\"\:(.*)/\"version\"\: \"$VERSION\",/" $PACKAGE_FILE


echo; echo "*** Mission Accomplished! ***"; echo;

I have saved this script in a file named version-manager.sh in the root of the project, and in my package.json file, I also created a script to run it when it is necessary to modify the version.

"change-version": "bash ./version-manager.sh"

Finally, I can just change the version by executing

npm run change-version 

This command will change the version in the index.html template and also in the package.json file. Following were the few screenshots taken from my existing app.

enter image description here

enter image description here

enter image description here

enter image description here

sanjeev
  • 129
  • 2
  • 4
  • 1
    My only concern with this solution is, that it modifies files in place and you risk accidental check-in of the modified files. I better solution IMHO was to let the build system modify the files on the fly so that the source folder remains clean and we only see the result in the dist folder or in a local dev-server. – lanoxx Sep 07 '21 at 08:57
5

This https://github.com/angular/angular-cli/issues/5190 had an interesting solution using a shell file to generate a version.ts file. @sanjeev had a similar solution in this forum.

This solution uses Node, javascript and the fs module to achieve the same. Works in linux for sure. Should work ok in Windows since Node/fs are cross-platform... right?

  1. add a line to package.json:

    {
      "version": "0.0.1",
      ... 
      "scripts": {
        "version": "node gen_version.js $npm_package_version",
         ...
      },
    ...
    }
    
  2. create gen_version.js (note: it's not typescript)

    var fs = require('fs');
    
    // arg[0]: node path
    // arg[1]: this script's path
    // arg[2]: 1st arg on command line
    console.log('current version: ' + process.argv[2])
    
    path = 'src/environments/version.ts'
    
    script = 'export class Constants {'
    script += '  static readonly version = \'' + process.argv[2] + '\''
    script += '}'
    
    fs.writeFile(path, script, function (err, file) {
      if (err) throw err;
      console.log('file saved:', path);
    });
    
  3. Run it from npm:

    npm run version
    
    > omnitool@0.0.1 version ...
    > node gen_version.js $npm_package_version
    
    current version: 0.0.1
    file saved: src/environments/version.ts
    
  4. use from your app:

    import {Constants} from "../environments/version"
    ...
    console.log('Version:', Constants.version)
    
JohnA
  • 699
  • 2
  • 7
  • 15
5

This answer is specific to Angular 12+. It uses Webpack 5.

According to webpack5 documentation

This is not supported by the new specification and you will get a warning. Instead of:

import { version } from './your-path/package.json';
console.log(version);

use:

import pkg from './your-path/package.json';
console.log(pkg.version);

Additionally you will have to provide in tsconfig.json

"compilerOptions": {
  ...
  "allowSyntheticDefaultImports": true,
  "resolveJsonModule": true,
  ...
IvanNickSim
  • 126
  • 3
  • 13
minigeek
  • 2,766
  • 1
  • 25
  • 35
4

I don't think that "Angle Bracket Percent" has anything to do with angular1. That's likely an interface to another API you don't realize is being used in your previous project.

Your easiest solution: just list the version number manually in your HTML file or store it in a global variable if you are using it in multiple places:

<script>
  var myAppVersionNumber = "0.0.1";
</script>
...
<body>
  <p>My App's Version is: {{myAppVersionNumber}}</p>
</body>

Your harder solution: run a build automation step that extracts the version number from your package.json file and then rewrites your index.html file (or js/ts file) to include the value:

  • Could simply import or require the package.json file, if you're working in an environment that supports it:

    var version = require("../package.json").version;

  • This could also be done in a bash script that reads the package.json and then edits another file.

  • You could add an NPM script or modify your start script to make use of additional modules to read and write files.
  • You could add grunt or gulp to your pipeline and then make use of additional modules to read or write files.
Cooper Buckingham
  • 2,503
  • 2
  • 15
  • 23
  • 1
    Without the tip to use require, this is actually the best answer. Because there will be no unnecessary/sensitive information in the production build. – Rafiek Feb 23 '18 at 13:47
  • `<% %>` usually indicates a .Net language like c# – danwellman Mar 29 '18 at 10:07
2

Angular 13+ / Ionic

This works for me:

Put it under both dev and prod environment files.

environment.ts

declare const require: any;

export const environment = {
 appVersion: require('../../package.json').version,
};

Sample usage on any component:

import { environment } from 'src/environments/environment';

     constructor() {
        console.log(environment.appVersion);
      }
Sampath
  • 63,341
  • 64
  • 307
  • 441
1

As an alternative to the solutions already proposed, I've created a simple JS script that writes the version to a constant in a .ts file, so it can be read as any other TS file.

I call this script before any new version change.

Here's the code:

// easier with fs-extra, but possible also with node build-in fs
const fs = require('fs-extra');

function storeVersionInTsFile() {
  const packageJson = fs.readJSONSync('./package.json');
  const file = `./src/app/version.ts`;
  const contents = `/**\n * Auto generated file, do not edit.\n */\n\nexport const appVersion = '${packageJson.version}';\n`;
  fs.writeFileSync(file, contents);
}

storeVersionInTsFile()

Contents of version.ts:

/**
 * Auto generated file, do not edit.
 */

export const appVersion = '0.3.2';

For convenience, I've also added a script in package.json:

...
"store-version": "node store-version.js",
"build": "npm run store-version && ng build --configuration production"
...
don
  • 4,113
  • 13
  • 45
  • 70
  • I tried this method but the `npm run....` simply seems to be ignored and not taken into effect. Do you know if any modifications are needed for Angular +13? – ilpianoforte May 30 '22 at 18:30
  • Mmm weird that npm run is ignored, are you running `npm run build` ? – don May 31 '22 at 08:57
  • I ran `ng build`, but I assume its the same effect. I have gathered my effort and findings in [this question](https://stackoverflow.com/questions/72403081/executing-a-javascript-file-when-running-ng-build). Perhaps you have a clue? – ilpianoforte May 31 '22 at 08:59
  • 1
    If you run `ng build` the npm script is ignored. You must run `npm run build` for this to work. You want to run the script from package.json, so that `npm run store-version` is executed before `ng build`. Also notice that in my example the `build` script contains the `--configuration production` flag, which you may not want, and most likely is no longer supported in Angular 13, so you probably want to remove it, so your script in package.json should be: `"build": "npm run store-version && ng build"`. – don May 31 '22 at 09:06
0

For anyone who doesn't like the idea of bringing package.json to the build folder, check out this plugin ngx-build-plus.


hint: use an injection token to provide the VERSION if you want to use it in different files hence no more declare statement.

Ezzabuzaid
  • 529
  • 1
  • 5
  • 13
-1

Without using package.json:

import { VERSION } from '@angular/core';

export const AppVersion = VERSION.major;
SpaceNinja
  • 496
  • 7
  • 20
  • It's return the core version of the @angular/core dependency and not the app version of the application – jdc Jul 19 '23 at 14:19
  • @jdc Interesting, I didn't know that. Can you explain the difference between the two? From the docs: "As of Angular version 7, the major versions of Angular core and the CLI are aligned. This means that in order to use the CLI as you develop an Angular app, the version of @angular/core and the CLI need to be the same." – SpaceNinja Aug 10 '23 at 14:40
-5

You could read package.json just like any other file, with http.get like so:

import {Component, OnInit} from 'angular2/core';
import {Http} from 'angular2/http';

@Component({
    selector: 'version-selector',
    template: '<div>Version: {{version}}</div>'
})

export class VersionComponent implements OnInit {

    private version: string;

    constructor(private http: Http) { }

    ngOnInit() {
        this.http.get('./package.json')
            .map(res => res.json())
            .subscribe(data => this.version = data.version);
    }
}
Presari
  • 106
  • 4
  • and as always confusing downvotes. why? is it bad answer? – Janatbek Orozaly Nov 20 '20 at 20:28
  • 5
    @JanatbekSharsheyev 1st) package.json won't be part of the build. So this approach won't work in the final release. And counteracting this by including package.json in the build is a bad idea too, because this will expose that file to the public which is not a clever idea, as it might contain sensitive data. 2nd) the version should absolutely be a hard-coded part of your delivered program - just to be sure the indicated one is actually the right one. – Holzchopf Jan 20 '21 at 10:11
  • Thanks for clarification. – Janatbek Orozaly Mar 11 '21 at 21:24