Using environment variables in npm scripts across platforms - npm

I am building a package.json and use "npm run" to run some scripts, to be exactly, https://docs.npmjs.com/misc/scripts.
My script would need to expand some environment variables and I want to make it cross platform compatible. For example, my script would say
"scripts": {
"build": "md %npm_package_version%\helloworld"
}
But it's currently running on Windows because the expansion of environment variables. Linux would use md $npm_package_version\helloworld.
Does npm comes with a mechanism to convert environment variables expansion so that it works across platforms?

To make it cross-platform, use cross-var:
"scripts": {
"build": "cross-var md %npm_package_version%\helloworld"
}

npm doesn't appear to have a cross platform way to expand environment variables, but you do have node at your disposal, so I'd recommend implementing all your scripts as node scripts, then you can access process.env and cross-platform filesystem functions, like mkdirSync.
package.json
"scripts": {
"build": "node utils/mdkir.js"
}
utils/mkdir.js
'use strict';
var fs = require('fs');
fs.mkdirSync(process.env.npm_package_version + '/helloworld');

Related

How to run shell scripts cross-platform, using npm

I have nestJS project with that line in package.json:
"scripts": {
...
"test": "sh scripts/test.sh",
...
},
And on my windows machine, it can't run.
How to rewrite it, to run cross-platform? May be example using cross-env-shell or add some package in dependencies?

Vue can I set process.env.NODE_ENV

Concerning modes and environmental variables as documented here
https://cli.vuejs.org/guide/mode-and-env.html#modes
I was rather confused why I can't set the following variable to mock for example. As the document seems to say this will be the mode that you pass in!
process.env.NODE_ENV
I have create the following server-mock command string in my package.json as follows
"serve-mock": "vue-cli-service serve --mode mock"
But when I run
npm run server-mock
The process.env.NODE_ENV is still set to development and not to mock. Am I supposed to set this in the .env.mock file? I presumed that it would be set based on the mode that was passed in as mock?
Vue CLI's serve command uses the mode option to load environment variables from mode-specific .env files. It also sets the NODE_ENV to one of the three standard modes (test, development, or production) only if not already set. However, if the specified mode is not standard (as is the case with mock), Vue CLI defaults to development.
So, you could set NODE_ENV=mock inside .env.mock to bypass the NODE_ENV setting mentioned above.
Alternatively, you could set NODE_ENV on the NPM script's command line in *nix shells:
{
"scripts": {
"serve-mock": "NODE_ENV=mock vue-cli-service serve"
}
}
For a cross-platform solution (including Windows), you could install cross-env (as recommended in comments), and edit your NPM script as follows:
{
"scripts": {
"serve-mock": "cross-env NODE_ENV=mock vue-cli-service serve"
}
}

Setting argv in the package.json and running a different script

I have two versions of my application, for one I set --extended, and for the other not, like this
"scripts": {
"build": "webpack --mode production",
"extended": "webpack --mode production --extended",
// ...
}
Now, in my webpack, I access the extended like this
module.exports = (_env,argv)=> {
argv.extended
}
I am trying to improve this in a cross platform way to do something like
"scripts": {
"build": "webpack --mode production",
"extended": "--extended npm run build"
}
as to run the build script from extended but still access the --extended variable.
I there a way to achieve this? Thank you
I read this whole question How to set environment variables from within package.json but can't find a way
Change the scripts section of your package.json to the following:
"scripts": {
"build": "webpack --mode production",
"extended": "npm run build -- --extended"
}
Explanation:
As stated in the npm-run-script documentation which can be found here:
... The special option -- is used by getopt to delimit the end of the options. npm will pass all the arguments after the -- directly to your script:
So, essentially when you run the following command via your CLI:
$ npm run extended
npm invokes the extended script, which then runs the build script and passes the --extended argument to the end of it (i.e. it passes --extended to the end of the build script).
Is there another way?
Yes, you could also consider simplifying the scripts section of your package.json further by deleting your extended script completely.
For instance:
"scripts": {
"build": "webpack --mode production"
}
Then you can do either of the following:
Run the following command via your CLI:
$ npm run build
This will to invoke your build script without the --extended argument/option.
Or run the following command via your CLI instead:
$ npm run build -- --extended
This will invoke your build script with the --extended argument/option.

How to overwrite environment variables in Vue-cli3?

Let us assume we have a Vue.js project build with Vue-cli3 , package.json:
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
...
}
Also, we have a plan to push our project to a public repository on GitHub, so we need different environment variables for public repo and for the local development.
Vue-cli 3 gives us modes: https://cli.vuejs.org/guide/mode-and-env.html#modes
I have such a files:
.env
.env.development
.env.production
.env.local
.env.development.local
.env.production.local
Content of .env:
NODE_ENV=production
VUE_APP_PATH=http://website.com/
VUE_APP_API_ROUTE=api/v1/
Content of .env.development:
NODE_ENV=development
VUE_APP_PATH=http://dev-website.com/
Content of .env.development.local:
NODE_ENV=development
VUE_APP_PATH=http://localhost:8080/
When I do npm run serve I expect process.env.VUE_APP_PATH will be equals http://localhost:8080/ but unfortunately it stills = http://dev-website.com/.
So, the problem is variables from local env files (i.e. .env.development.local) are not overwrite existed from another env file (i.e. .env.development).
How can I use this vue-cli approach to overwrite neccessary variables? The documentation tells about priority: An env file for a specific mode (e.g. .env.production) will take higher priority than a generic one (e.g. .env). but with .local files it doesn`t work.
You can pass in the --mode option within the npm script. So, in your instance you might want the serve script to look like:
vue-cli-service serve --mode development.local
If you wanted to test out serving your non-local development configuration you could copy the serve script and rename it serve:local and then edit the original serve script to look like this:
vue-cli-service serve --mode development
Which is really the actual default mode for serve out-of-the-box with CLI 3. We've just explicitly set the mode.

How to use a package script under a different platform?

I have to have this line package.json
"scripts": {
"default_linux": "export NODE_ENV=default&& export NODE_MINIFIED=false&& webpack",
"default_windows": "set NODE_ENV=default&& set NODE_MINIFIED=false&& webpack",
"default_linux_min": "export NODE_ENV=default&& export NODE_MINIFIED=true&& webpack",
"default_windows_min": "set NODE_ENV=default&& set NODE_MINIFIED=true&& webpack",
},
But to run a not very nice to think about each version separately and so as to correctly configure scripts for different platforms to make it as a team, not ..?
$ npm run default_linux # frontend assembly under linux
You can use the cross-env package on npm. It allows you to use unix style scripts, and handles all the cross-platform issues. It works for linux and windows, but I haven't tested it for Mac. Also, there's no need for export.
After you install cross-env, you can replace your scripts field with this:
"scripts": {
"build": "cross-env NODE_ENV=default NODE_MINIFIED=false webpack",
"build-min": "cross-env NODE_ENV=default NODE_MINIFIED=true webpack",
},