【问题标题】:How to insert a Build Number or Timestamp at build time in AngularCLI如何在 Angular CLI 的构建时插入内部版本号或时间戳
【发布时间】:2017-01-19 04:18:10
【问题描述】:

我想在我的 Angular2 应用程序的某处有一个时间戳或内部版本号,这样我就可以判断用户是否使用旧的缓存版本。

如何在 AOT 编译/构建时使用 Angular2 中的 AngularCLI 执行此操作?

【问题讨论】:

    标签: angular angular-cli


    【解决方案1】:
    1. 安装pluginnpm install replace-in-file --save-dev
    2. 添加到 prod 环境 src/environments/environment.prod.ts new 属性

      export const environment = {
          production: true,
          version: '{BUILD_VERSION}'
      }
      
    3. 将构建文件replace.build.js 添加到文件夹的根目录

      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. 将脚本添加到 package.json

      "updateBuild": "node ./replace.build.js"
      
    5. 在您的应用中使用environment.version

    6. 在构建之前调用npm run updateBuild -- 1.0.1

    PS。您必须始终记住 {BUILD_VERSION} 永远不会被提交。

    PS。我在my blog写了一个更好的解决方案

    PS.3 正如@julien-100000 提到的,您不应该使用更新版本提交 environment.prod.ts。版本更新必须仅在构建过程中发生。并且永远不应该提交。

    【讨论】:

    • 谢谢,这正是我想要的。一些不错的增强功能是生成时间戳或自动增加内部版本号(而不必输入它)。
    • @Rodney 实际上我只是想到了这一点。会这样做并写在我的博客中:)
    • replace-in-file 模块已更新其选项。应该使用const options = { files: 'src/environments/environment.prod.ts', from: /{BUILD_VERSION}/g, to: buildVersion };
    • 实际上应用程序版本无论如何都存储在 package.json 中。有什么方法可以使用吗?
    • 对于那些不想在意不提交 environment.prod.ts` 的人的一个建议,您可以更改正则表达式。这是一个示例,我还添加了构建时间戳。 let const buildVersionOptions = { files: 'src/environments/environment.prod.ts', from: /version:.*/gm, to: `version: '${buildVersion}',`, allowEmptyPaths: false, }; const timeStampOptions = { files: 'src/environments/environment.prod.ts', from: /buildTimestamp:.*/gm, to: `buildTimestamp: '${new Date().toISOString()}',`, allowEmptyPaths: false, };
    【解决方案2】:

    将此步骤添加到您的构建中(即 Jenkins-Job):

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

    您可以这样访问号码:

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

    这个解决方案是+轻量级+易读+健壮

    【讨论】:

    • 詹金斯的工作是什么?也有不同的 CI 解决方案,没有任何问题。
    • @Rantiev 你说得有道理。然而,这种简单的方法应该适用于几乎任何构建环境(可能使用稍微修改的 shell 脚本)。我更新了我的帖子。
    • 这是最简单最好的解决方案。我在我的情况下使用了以下命令echo "export const RunTimeFile = { buildtime:new Date('$(date -Is)') };" | tee src/environments/runtime-file.ts
    【解决方案3】:

    不需要replace-in-file

    简单的解决方案:使用 Angular 环境

    就在您想要的环境中。*.ts 文件(有关环境的更多信息请阅读angular-2-and-environment-variables)需要package.json,如下所示:

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

    然后在你的应用导入环境中:

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

    你有environment.version。 如果您收到cannot find name 'require' 错误,请阅读this answer

    More info

    注意:正如 cmets 中提到的@VolodymyrBilyachat,这将在最终的捆绑文件中包含您的 package.json 文件。

    【讨论】:

    • 太棒了,但这是一个困扰我的问题。摇树如何与 require 一起工作?
    • @VolodymyrBilyachat 我不确定我是否理解这一点,但摇树是关于删除未使用的代码。我发现了这个可能相关的链接:Angular Tree Shaking。阅读标题“为什么需要 Typescript 2”
    • 好吧,让我问你其他问题。构建应用程序后,您是否查看过缩小的脚本?
    • @VolodymyrBilyachat 没有。我应该寻找什么?
    • 我问 require 如何与 tree shaking 一起工作的原因是因为它基本上将所有东西都注入到你的包中。因此,如果您确实需要 package.json,您应该了解该文件的全部内容将捆绑到您的最小脚本中。如果你很好,那很好。是的,您的链接与我的问题完全无关
    【解决方案4】:

    我通过在index.html 的末尾附加一个带有最后提交哈希的注释来解决这个问题。例如:

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

    然后您可以在浏览器中执行“查看源代码”,查看 HTML 的底部,并查看您的应用的部署版本。

    这当然假设您使用 git 作为版本控制系统。您可以使用任何其他输出唯一版本的命令轻松更改 git rev-parse HEAD

    【讨论】:

    • 我对“构建”和“内部版本号”的理解是它们不等同于提交——在提交之前可能有很多构建。
    • 我使用了你的方法并做了:date/T >> dist\index.html(在创建最后一个构建时给我信息)对我来说很好!
    • 感谢这个技巧。我正要在这里问一个问题,然后偶然发现了你的答案。
    • 这很有帮助。我也想添加构建日期,所以我使用了以下内容: printf '\n' "$(git rev-parse HEAD)" " $(TZ='America/New_York' 日期)"
    【解决方案5】:

    讨论可能有点晚了,但希望我可以帮助其他人解决同样的问题。

    我编写了一个名为 angular-build-info 的小型 npm 包,它总结了有关当前构建的一些信息,例如 构建时间戳、构建应用程序的 git 用户、缩短的提交哈希和您的项目 package.json 文件中的应用程序版本。

    实现这个包也很简单,它会在src/build.ts 下创建一个build.ts 文件,然后您可以将其导入到您的Angular 应用程序中并在任何地方显示信息。

    实现它的示例如下所示:(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"
            );
        }
    }
    

    会输出: link to console screenshot

    我希望这会对某人有所帮助! :)

    【讨论】:

    • 不错的包,但我不想为这个简单的功能在我的项目中添加另一个依赖项。
    【解决方案6】:

    我查看了其他解决方案,但我并没有被使用另一个包或生成 JSON 所说服(因为 JSON 并不完全在应用程序中)。另外,我不想为未提交的更改而烦恼,例如在该线程的已接受答案中。

    我最终制作了一个小型 bash 脚本,该脚本自动将位于我的应用程序某处的字符串替换为从 GIT 获得的版本 + 构建的日期时间。

    现在,当我构建我的应用程序时,我只需要执行以下脚本:

    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
    

    在我的文件 user-preference.component.html

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

    【讨论】:

    • 这是一个非常棒的解决方案,没有依赖关系,易于集成到构建步骤中。
    • 谢谢!这种方法的另一个优点是它可以与其他部署操作集成。就我而言,我需要为项目实施团队生成一个 zip 文件夹,因此我添加了: zip -rq ... ... ; scp .... :)
    【解决方案7】:
    1. 创建简单的js文件createBuildDate.js

      例如:

      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. 在 package.json 中编辑脚本

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

      或者你可以使用prebuild

    3. 编辑 tsconfig.json

      "resolveJsonModule": true,
      
    4. 在组件中导入json并使用

    【讨论】:

      【解决方案8】:

      仅供参考,这里是slartidan's answer 的平台无关版本。在构建期间使用 node.js 脚本 (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);
        }
        
      }
      

      【讨论】:

        【解决方案9】:

        如果您不仅想记录/显示版本号,还想记录来自 git 的信息(如哈希、标签等),您可以考虑为我创建的 angular-cli 使用自定义示意图。将其添加到您的 Angular 8+ 应用程序就像执行一样简单 ng add @w11k/git-info

        有关更多文档和见解,您可以查看https://github.com/w11k/angular-git-info 上提供的文档

        【讨论】:

          【解决方案10】:

          也许这对某人来说是一个很好的解决方案.. https://medium.com/@amcdnl/version-stamping-your-app-with-the-angular-cli-d563284bb94d

          他描述的是如何使用你的 git 数据并将最后的提交哈希作为内部版本号。

          通过在 package.json 中添加安装后步骤,运行安装脚本时将生成一个文件。

          【讨论】:

            【解决方案11】:

            我认为适合您的情况:ng buildng serve 添加 environment.ts

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

            然后在你的组件中:

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

            这就是我要找的。​​p>

            【讨论】:

            • 这不会保留构建的时间戳。每次页面加载时都会更新。
            猜你喜欢
            • 1970-01-01
            • 2016-05-14
            • 2018-06-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-06
            • 1970-01-01
            相关资源
            最近更新 更多