web-dev-qa-db-ja.com

npmスクリプトでノード環境変数を動的値に設定します

Npmスクリプトで環境変数を動的に設定したいと思います。

Windowsで開発していて、サーバーがUnixベースであるため、_cross-env_を使用しています。環境変数を現在の日付(new Date())で初期化して、_create-react-app_でアクセスしてレンダリングできるようにします。

これは機能します(ハードコードされた文字列):

_"scripts": {
  "start": "cross-env-Shell REACT_APP_BUILD_DATE=\"currentDate\" react-scripts-ts start",
}
_

明らかに、currentDateは文字列ではなく、次の式の結果である必要があります:new Date()

どうすればそれを達成できますか?言い換えると、通常のJavaScriptを評価し、その結果をnpmスクリプトで使用するにはどうすればよいでしょうか。それともこれは不可能ですか?

5
PzYon

呼び出されたスクリプトに環境変数を渡すために、単純なノードスクリプトを使用しています。 child_process.execSyncを使用します。

// File name: ./build.js
/* eslint-env node */
const execSync = require('child_process').execSync;
const env = Object.create(process.env);

env.REACT_APP_BUILD_DATE= Date.now();

console.log('Used env variables: ' + JSON.stringify(env));
console.log('Run command: react-scripts start');
execSync('react-scripts-ts start', { env: env, stdio: 'inherit' });

Package.jsonスクリプトのstartコマンドを更新します。このような:

"scripts": {"start": "node ./build.js"}
2
Michal Biros

念のため、現在、次のアプローチを使用しています。package.jsonのカスタムプロパティに現在の日付を書き込み、package.jsonをインポートしてアプリでその値を読み取ります。

package.json

"scripts": {
  "start": "react-scripts-ts start",
  "build": "node ./update-packagejson.js && react-scripts-ts build"
}

pdate-packagejson.js

const fs = require("fs");
const filePath = "./package.json";

const packageJson = JSON.parse(fs.readFileSync(filePath).toString());
packageJson.ngrvd.buildDate = new Date().toUTCString();

fs.writeFileSync(filePath, JSON.stringify(packageJson, null, 2));

コンポーネント

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

// ... 

private static getAppInfo(): string {
  const buildDate = process.env.NODE_ENV === "development" ? new Date() : ngrvd.buildDate;
  return "Version " + version + "  - Built " + moment(buildDate).fromNow();
}

これはどのような環境でも機能し、シンプルで理解しやすく、他の情報も含めるように拡張できます。開発モードでは、毎回ローカルで変更されるのを防ぐためにpackage.jsonに書き込みません。

1
PzYon

この特定のケースでは、JavaScriptの代わりにShellコマンドを使用する方がよいため、次のようになります。

"scripts": {
  "start": "cross-env-Shell REACT_APP_BUILD_DATE=$(date '+%F %H:%M:%S') react-scripts-ts start",
}
0
bredikhin

私はあなたのためにそれを行うカスタムjavascriptスクリプトを作成します:

execute.js

var spawn = require('child_process').spawn;

// because first arg will actually be something like "./execute.js"
// this is the "regular javascript" you want to evaluate
var arg1 = process.argv[1];
// so lets eval it
var res = eval(arg1);
// this is the remaining args, that is the command you want to run (and its args)
var command = process.argv[2];
var commandArgs = process.argv.slice(3);
// if arg1 evaluation resulted in a value, append this value to the list of args
if (res) {
    commandArgs.Push(res);
}
// execute the command
var prc = spawn(command, commandArgs);

スクリプト定義は次のようになります。

"scripts": {
    "start": "cross-env-Shell ./execute.js \"process.env.REACT_APP_BUILD_DATE = new Date();\" react-scripts-ts start",
}

または同様のもの。

これはテストされていませんが、「通常のJavaScriptを評価し、その結果をnpmスクリプト」のソリューションで開始する必要があります。

ただし、環境変数に日付を設定するだけの場合は、@ bredikhinのソリューションの方が適しています。

環境変数を処理するための代替ソリューション

プロジェクトのルートにある.envfileに(手動またはプログラムで)書き込む余裕がある場合は、 dotenv を使用して環境変数にデータを入力できます( から) dotenv ドキュメント):

// Usage
// As early as possible in your application, require and configure dotenv.

require('dotenv').config()
/* Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE. For example:

DB_Host=localhost
DB_USER=root
DB_PASS=s1mpl3
That's it.

process.env now has the keys and values you defined in your .env file.
*/
const db = require('db');
db.connect({
    Host: process.env.DB_Host,
    username: process.env.DB_USER,
    password: process.env.DB_PASS
});
0
remix23