问题
I would like to set an environment variable dynamically in an npm script.
I'm using cross-env
as I'm developing on Windows and the server is Unix-based. I want to initialize an environment variable with the current date (new Date()
) so I can access and render it in my create-react-app
:
This works (hard-coded string):
"scripts": {
"start": "cross-env-shell REACT_APP_BUILD_DATE=\"currentDate\" react-scripts-ts start",
}
Obviously, currentDate
shouldn't be a string but the result of following expression: new Date()
.
How can I achieve that? In other words: How can evaluate some regular JavaScript and use its result an npm script? Or is this not possible?
回答1:
I am using simple node script for passing environment variables into called script. It uses 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' });
Update start command in package.json scripts. like this:
"scripts": {"start": "node ./build.js"}
回答2:
Just for the record, I'm now using following approach: Write current date to a custom property in package.json and read that value in the app by importing package.json
package.json
"scripts": {
"start": "react-scripts-ts start",
"build": "node ./update-packagejson.js && react-scripts-ts build"
}
update-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));
Component
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();
}
This works on any environment, is simple and understandable and could be extended to also contain other information. When in dev mode I don't write to package.json
to prevent having local changes everytime.
回答3:
In this particular case you'd be better off using shell command instead of JavaScript, so it should be something like the following:
"scripts": {
"start": "cross-env-shell REACT_APP_BUILD_DATE=$(date '+%F %H:%M:%S') react-scripts-ts start",
}
回答4:
I'd create a custom javascript script doing it for you:
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);
and your script definition will become:
"scripts": {
"start": "cross-env-shell ./execute.js \"process.env.REACT_APP_BUILD_DATE = new Date();\" react-scripts-ts start",
}
Or something similar.
This is untested but should get you started on a solution for "evaluate some regular JavaScript and use its result an npm script"
But if you only want to set a date in a env variable, the solution from @bredikhin is better.
ALTERNATIVE SOLUTION TO DEAL WITH ENVIRONMENT VARIABLES
If you can afford to write into an .env
file at the root of your project (by hand or programatically), you can then use dotenv to populate environment variables with it (from dotenv documentation):
// 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
});
来源:https://stackoverflow.com/questions/52174249/set-node-environment-variable-to-dynamic-value-in-npm-script