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:

<%=version %>

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

Zbynek

Ответов: 16

Ответы (16)

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

  • TypeScript 2.9 or later! (Supported from Angular 6.1 upwards)

Steps:

  1. In your /tsconfig.json (sometimes also necessary in /src/tsconfig.app.json) enable the resolveJsonModule 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:
    import { version } from '../../package.json';
    ...
    export class AppComponent {
      public version: string = 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 will not include the package.json contents, only the version number.
Tested w/Angular8/Node10/TypeScript3.4.3.

Please update your apps to use this solution cause depending on the contents of your package.json the original solution may implicate security issues.

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');

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:


...

  

My App's Version is: {{myAppVersionNumber}}

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.

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.

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

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>/

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

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

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 './package.json';
console.log(version);

use:

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

Additionally you will have to provide in tsconfig.json

"compilerOptions": {
  ...
  "allowSyntheticDefaultImports": true
  ...

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: '
Version: {{version}}
' }) 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); } }

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

{{'general.version' | translate}}: {{version}}

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.

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)
    

Since Angular 12 (webpack 5) we should do imports from package.json this way:

before:

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

after:

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

also tsconfig.json should be updated with:

"compilerOptions": {
  "allowSyntheticDefaultImports": true

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, { flat: '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;
}

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

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
  }
}

2022 WebDevInsider