How to insert a Build Number or Timestamp at build time in AngularCLI

AngularAngular Cli

Angular Problem Overview


I want to have a timestamp or build number somewhere on my Angular2 App so I can tell if a user is using an old cached version or not.

How to do this with AngularCLI in Angular2 at AOT compile/build time?

Angular Solutions


Solution 1 - Angular

  1. Install plugin npm install replace-in-file --save-dev

  2. Add to prod environment src/environments/environment.prod.ts new property

    export const environment = {
        production: true,
        version: '{BUILD_VERSION}'
    }
    
  3. Add build file replace.build.js to root of your folder

    var replace = require('replace-in-file');
    var buildVersion = process.argv[2];
    const options = {
        files: 'src/environments/environment.prod.ts',
        from: /{BUILD_VERSION}/g,
        to: buildVersion,
        allowEmptyPaths: false,
    };
            
    try {
        let changedFiles = replace.sync(options);
        console.log('Build version set: ' + buildVersion);
    }
    catch (error) {
        console.error('Error occurred:', error);
    }
    
  4. add scripts to package.json

    "updateBuild": "node ./replace.build.js"
    
  5. Use environment.version in your app

  6. Before build call npm run updateBuild -- 1.0.1

PS. You must always remember that {BUILD_VERSION} is never committed.

PS. I wrote a bit better solution in my blog

PS.3 as @julien-100000 mentioned you should not commit environment.prod.ts with updated version. Version update must happen only in build process. And should never be committed.

Solution 2 - Angular

Add this step to your build (ie Jenkins-Job):

echo export const version = { number: '%SVN_REVISION%' } > src\version.ts

You can access the number like this:

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

export class AppComponent {
    constructor() {
        console.log("MyApp version " + version.number);
    }
}

This solution is + lightweight, + easy to read, + robust.

Solution 3 - Angular

There's no need to replace-in-file.

Simple Solution: Using Angular Environments

Just inside your desired environment.*.ts file (For more information about environments read angular-2-and-environment-variables) require package.json like so:

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

Then inside your app import environment:

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

And you have environment.version. If you get cannot find name 'require' error, Read this answer

More info

Note: As @VolodymyrBilyachat mentioned in comments, this will include your package.json file in the final bundle file.

Solution 4 - Angular

I solved this by appending a comment at the end of index.html with the last commit hash. For example:

ng build --prod

git rev-parse HEAD | awk '{print "<!-- Last commit hash: "$1" -->"}' >> dist/index.html

You can then do a "View Source" in the browser, look at the bottom of the HTML, and see the deployed version of your app.

This of course assumes that you use git as the versioning system. You could easily change git rev-parse HEAD with any other command that outputs a unique version.

Solution 5 - Angular

May be a bit late for the discussion, but hopefully I can help someone else looking at the same problem.

I have written a small npm package called angular-build-info which sums up some information about the current build such as a build timestamp, the git user which built the app, a shortened commit hash and the apps version from your projects package.json file.

Implementing the package is also pretty easy, it creates a build.ts file under src/build.ts which you can then import in your Angular app and display the information anywhere.

An example of implementing it could look as follows: (app.component.ts)

import { Component } from "@angular/core";
import { buildInfo } from "../build";
import { environment } from "../environments/environment";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    styleUrls: ["./app.component.css"]
})
export class AppComponent {
    constructor() {
        console.log(
            `\n%cBuild Info:\n\n%c ❯ Environment: %c${
                environment.production ? "production 🏭" : "development 🚧"
            }\n%c ❯ Build Version: ${buildInfo.version}\n ❯ Build Timestamp: ${
                buildInfo.timestamp
            }\n ❯ Built by: ${buildInfo.user}\n ❯ Commit: ${buildInfo.hash}\n`,
            "font-size: 14px; color: #7c7c7b;",
            "font-size: 12px; color: #7c7c7b",
            environment.production
                ? "font-size: 12px; color: #95c230;"
                : "font-size: 12px; color: #e26565;",
            "font-size: 12px; color: #7c7c7b"
        );
    }
}

which would output: link to console screenshot

I hope this will help someone! :)

Solution 6 - Angular

  1. Create simple js file createBuildDate.js

    for example:

    const { writeFileSync } = require('fs')
    const { join } = require('path')
         
    const TIME_STAMP_PATH = join(__dirname, 'buildDate.json');
         
    const createBuildDate = {
        year: new Date()
    }
         
    writeFileSync(TIME_STAMP_PATH, JSON.stringify(createBuildDate, null, 2));  
    
  2. Edit script in package.json

    "build": "node src/environments/createBuildDate.js && ng build"
    

    or you can use prebuild

  3. Edit tsconfig.json

    "resolveJsonModule": true,
    
  4. Import json in component and use

Solution 7 - Angular

I looked at other solutions, but I have not been convinced by either using yet another package or generating a JSON (because the JSON is not exactly in the app). Also, I did not want to bother with uncommitted changes like in the accepted answer of this thread.

I end-up by making a tiny bash script that replaces automatically a string located somewhere in my App with the version got from GIT + the DateTime of the build.

Now when I build my app, I just need to execute the following script:

latesttag=$(git describe --tags)
now=$(date +'%a %y-%m-%d %H:%M')

sed -i '' "s/build_info/$latesttag/g" ./src/app/pages/home/user-preference/user-preference.component.html
sed -i '' "s/build_time/$now/g" ./src/app/pages/home/user-preference/user-preference.component.html

ng build --prod;

sed -i '' "s/$latesttag/build_info/g" ./src/app/pages/home/user-preference/user-preference.component.html
sed -i '' "s/$now/build_time/g" ./src/app/pages/home/user-preference/user-preference.component.html

And in my file user-preference.component.html

<footer class="footer mt-auto">
	<div class="container text-center">
		Build: build_info - build_time
	</div>
</footer>

Solution 8 - Angular

Just for reference, here is a platform-independent version of slartidan's answer. The timestamp is updated during build using a node.js script (bin/update-timestamp.js).

bin/update-timestamp.js

#!/usr/bin/env node
'use strict';

const fs = require('fs');
const stamp = new Date().toISOString();
fs.writeFileSync('./src/app/timestamp/Timestamp.ts', `export class Timestamp { public static readonly stamp = '${stamp}'; }`);

package.json

{
  "scripts": {
    "build": "node ./bin/update-timestamp.js && ng build --prod",
  },
}

app.component.ts

import {Timestamp} from './timestamp/Timestamp';

export class AppComponent {

  constructor() {
    console.log("timestamp", Timestamp.stamp);
  }
  
}

Solution 9 - Angular

If you want to log/display not only the version number but also information from git (like the hash, tag, etc) you can consider using a custom schematic for the angular-cli that I created. Adding it to your Angular 8+ Application is as simple as executing ng add @w11k/git-info

For further Documentation and insights you can look at the documentation available at https://github.com/w11k/angular-git-info

Solution 10 - Angular

Perhaps this is a good solution for someone.. https://medium.com/@amcdnl/version-stamping-your-app-with-the-angular-cli-d563284bb94d

What he describes is how to use your git data and have the last commit hash as build number.

By adding a postinstall step in your package.json a file will be generated when running the install script.

Solution 11 - Angular

I think for your case: ng build or ng serve add in environment.ts:

export class environment {
  production: false,
  buildTimestamp: new Date()
}

Then in your component:

import { environment } from 'src/environments/environment'; // or path to your environment.ts file

...

const buildTimestamp = environment.buildTimestamp;

This is what I was looking for.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRodneyView Question on Stackoverflow
Solution 1 - AngularVova BilyachatView Answer on Stackoverflow
Solution 2 - AngularslartidanView Answer on Stackoverflow
Solution 3 - AngularVahidView Answer on Stackoverflow
Solution 4 - AngulartedwView Answer on Stackoverflow
Solution 5 - AngularJuri AdamsView Answer on Stackoverflow
Solution 6 - AngularklivladimirView Answer on Stackoverflow
Solution 7 - AngularPierreView Answer on Stackoverflow
Solution 8 - AngularDanView Answer on Stackoverflow
Solution 9 - AngularKai HenzlerView Answer on Stackoverflow
Solution 10 - AngularMackelitoView Answer on Stackoverflow
Solution 11 - AngularAndrei DigoriView Answer on Stackoverflow