Hi guys I am working on a vite project where I need to use esbuild-wasm to build some user-provided code. I have some code like
import * as esbuild from "esbuild-wasm"
// some initialization
await esbuild.build({
// other configurations
define: {"process.env.NODE_ENV": "production"}
})
where the define key should set env vars for esbuild-wasm. But when I run vite to serve locally the "process.env.NODE_ENV" is being interpolated by vite to become ""development"" in the browser, which causes syntax error. Is there a way to prevent this behaviour?
Related
Vite's docs say
Vite exposes env variables on the special import.meta.env object
But, when targeting es6 (i.e. viteConfig.esbuild.target === "es6"), Vite emits warnings on each access of import.meta, saying import.meta is not available in the configured environment. The files with import.meta.env.foo are .ts files that will run on the client.
In this case, should they be accessed via process.env, and does Vite guarantee they'll be there? Or instead should this be handled with a string-replacing rollup plugin?
I'm using Nuxt & Axios but having trouble using environment variables when building the application from my local machine.
I have installed the #nuxtjs/dotenv module in an attempt to fix this issue but still having problems.
Note: The environment variables work fine when building the app within my hosting providers environment. It is only building from my local machine that gives me trouble. My IDE is VS Code.
Here is my axios setup inside nuxt.config.js:
module.exports = {
...
buildModules: [
'#nuxtjs/dotenv'
],
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios'
],
axios: {
baseURL: process.env.BASE_URL
},
...
}
My .env file has the following:
BASE_URL="https://some.api.com"
The .env variables are not being recognized when building the app:
nuxt build
Instead, it just sets the axios base url to the same host:port that the server runs on by default. Ex: localhost:4000
I found the following documentation from #nuxtjs/dotenv module: https://github.com/nuxt-community/dotenv-module#using-env-file-in-nuxtconfigjs. This instructs you to add the following to the top of nuxt.config.js:
require('dotenv').config()
This works for building locally; my variables from .env are recognized! However, because dotenv is a dev dependency, this causes the build to crash when deployed to my hosting provider because the module isn't recognized.
I know that I can define the environment variables directly in the build command as follows but I would prefer NOT to do so:
NUXT_ENV_BASE_URL=some.api.com nuxt build
Is there an easy way to get environment variables to work locally inside of nuxt.config.js during the build process that also works well when deploying to production??
Thank you!
Updated 2020-09-26
As of 2.13.0 I have removed #nuxtjs/dotenv. My nuxt.config.js now simply reads as below with the dotenv imports removed. I made no other code changes and the rest functions exactly the same for me.
env: {
DB_HOST: process.env.DB_HOST
},
My .env contains the following.
DB_HOST=http://localhost:5001/
Original answer
I installed the following as a dev dependency; #nuxtjs/dotenv. Then I added the following to my nuxt.config.js. I found this import statement in an article and tried it. Thankfully it worked for me.
import dotenv from "dotenv";
dotenv.config();
env: {
DB_HOST: process.env.DB_HOST
},
I created a file called .env with the following content
DB_HOST=http://localhost:5001/
In nuxt version v2.13.0, support for Runtime Config was added. This adds proper support to read environment variables at runtime. Previously they could be read but were compiled into the application.
The standard documentation is pretty good: https://nuxtjs.org/guide/runtime-config/ .
There is also a great blog post on how to migrate. You remove the use of #nuxtjs/dotenv.
https://nuxtjs.org/blog/moving-from-nuxtjs-dotenv-to-runtime-config/
For example, in your nuxt.config.js, you define.
// Public env variables that are exposed on the frontend.
publicRuntimeConfig: {
someAccessKeyId: process.env.SOME_ACCESS_KEY_ID,
},
// Private env variables that are not be exposed on the frontend.
privateRuntimeConfig: {},
Then in your vue code, you access it via.
const { someAccessKeyId } = this.$config
My NX application's npm run build:server calls ng build api-server that triggers the #nrwl/node:build builder.
It builds the NestJS application as main.js. Things work except I wanted process.env.NODE_ENV to be evaluated at runtime but I think it was resolved at build time (via Webpack).
Currently, the value is always set to 'development'.
I am new to Nrwl's NX. Any solution this?
In NestJs/Nodejs app in Nx.Dev workspace process.env.NODE_ENV is replaced during compilation from typescript to javascript very "smart way" to "development" string constant (everything like NODE_ENV is replaced). I don't know why. But only way how can I get real NODE_ENV in runtime is this code:
//process.env.NODE_ENV
process.env['NODE' + '_ENV']
The reason you're seeing development is because you're building the app in development mode - it's not best practice to evaluate at runtime because then the builder can't do fancy things to make the build production ready. If you want production, you need to build the app in production mode by adding the --prod flag (just like how you need to build Angular in production mode).
If you need to serve the app in production mode (instead of build) the default config doesn't provide you with a prod mode for serve. You'll need to add the configuration to your angular.json.
So this code:
"serve": {
"builder": "#nrwl/node:execute",
"options": {
"buildTarget": "api-server:build"
}
},
Would become
"serve": {
"builder": "#nrwl/node:execute",
"options": {
"buildTarget": "api-server:build"
},
"configurations": {
"production": {
"buildTarget": "api-server:build:production"
}
}
},
and then you can run
ng serve --project=api-server --prod
Indeed the nx builder will replace the expression process.env.NODE_ENV in our source code with the current value of the env var (or the nx-mode).
What happens is this:
the build command executes the nx builder which creates a configuration for web-pack
this configuration instructions for the webpack-define plugin to replace the text process.env.NODE_ENV during compilation with the actual value of the env-var (or the nx-mode):
see nx-code getClientEnvironment()
Since the webpack-define plugin will look for the text process.env.NODE_ENV, it's easy to use a workaround as explained in this answer:
process.env['NODE'+'_ENV']
Warning
When you need to apply this workaround to make your app work, then something is wrong. Since you have compiled your app in production mode, it does not make sense to pass another value for NODE_ENV when you start the (production) app.
The webpack Production page contains some helpful info.
We also had this case, and the issue was, that we relied on the NODE_ENV variable to load different database configs for dev, prod, test, etc.
The solution for our case was to simply use separate env-vars for the database config (e.g. DB_NAME, DB_PORT, ..), so that we can use different db-configs at runtime with any build-variants: dev, prod, test, etc.
I recently faced the same problem using Express instead of Nest.
What we did to overcome this was adding some file replacements when compiling for any of our environments (development, production, staging, staging-dev). This is done in the angular.json file the same way the environment files are replaced for the Angular app .
Another approach that worked for us, was loading the environment variables only once, and retrieve them from that origin. As our app relies on Express for it's backend the used the Express env variable as:
import express from 'express';
const _app = express();
const _env = _app.get('env');
console.log(_env); // shows the right environment value set on NODE_ENV
To come to this conclusion we checked Express code for the env variable and it does use process.env.NODE_ENV internally.
Hope it helps. Best regards.
We had the same issue, we eventually used the cross-env package in our package.json:
"prodBuild": "cross-env NODE_ENV=production nx run api-server:build:production",
"prodServe": "cross-env NODE_ENV=production nx run api-server:serve:production"
process.env is indeed only available at run-time. What is probably happening is that you are not setting this value when running your application. Can I ask how you are running it?
As a trivial example
# The following will read the environment variables that are defined in your shell (run `printenv` to see what those are)
> node main.js
# this will have your variable set
> NODE_ENV=production node main.js
Of course you want to have it actually set in your environment when deploying the app rather then passing it in this way, but if you're doing it locally you can do it like this.
I have a react app , created with create-react-app then I build the app with command: npm run build
It's using serve to run the app after build, if we start the app with development code by running ENV=production npm run start it can read the process.env.ENV variable beacause I'm adding this plugins to webpack dev config
new webpack.DefinePlugin({
'process.env':{
'ENV': JSON.stringify(process.env.ENV),
}
}),
I also add the script above to webpack prod config, but if I try this command after build ENV=prod serve -s build, it cannot read the environment variable
How to fix this?
If you set all the environment variables inside the app.config.js, you can replace them after the build in the main.????????.chunk.js file.
A sample app.config.js could look like:
export default {
SOME_URL: "https://${ENV_VAR_1}"
SOME_CONFIGURATION: "${ENV_VAR_2}",
}
Leave the app.config.js file as is, without replacing the environment variables with their actual values. Then, create the optimized production build:
npm ci # if not already installed
npm run build
If the default webpack configurations are used, the contents of app.config.js will be bundled in build/static/js/main.????????.chunk.js. The values of the environment variables can be be envsubst, with a bash script like this:
main_chunk=$(ls build/static/js/main.*.js)
envsubst <$main_chunk >./main_chunk_temp
cp ./main_chunk_temp $main_chunk
rm ./main_chunk_temp
Note: In the above example, envsubst reads the actual variables set in the environment at runtime and literally replaces ${ENV_VAR_1} and ${ENV_VAR_2} with them. So, you can only run this once as the chunk is being over-written.
The reason why you can not read the ENV var is because:
(1) In development mode webpack watches your files and bundles you app on the fly. It also will read (because of the DefinePlugin) your process.env.ENV and will add it as a global variable. So it is basically piping variables from process.env to your JS app.
(2) After you've build your app (with webpack) everything is already bundled up into one or more files. When you run serve you just start a HTTP server that serves the static build files. So there is no way to pipe the ENV to you app.
Basically what the DefinePlugin does is add a var to the bundle. E.g.
new webpack.DefinePlugin({
'token': '12356234ga5q3aesd'
})
will add a line similar to this:
var token = '12356234ga5q3aesd';
since the JS files is static there is no way to change this variable after you've build/bundled it with webpack. Basically, when you do npm run build you're creating the compiled binary/.dll/.jar/... file and can no longer influence its contents via the plugin.
You can add a .env file to the root of your project and define your environment variables there. That will be your default (production) environment variables definition. But then you can have a local file called .env.local to override values from the default.
When defining your environment variables, make sure they start with REACT_APP_ so your environment variable definitions would look like this:
REACT_APP_SERVER_URL=https://my-awesome-app.herokuapp.com
Also, add this to .gitignore so you don't commit your local overrides:
.env*.local
Reference:
Adding Development Environment Variables In .env (create-react-app)
From create-react-app documentation:
Your project can consume variables declared in your environment as if
they were declared locally in your JS files. By default you will have
NODE_ENV defined for you, and any other environment variables starting
with REACT_APP_.
You can read them from process.env inside your code:
render() {
return (
<div>
<small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
<form>
<input type="hidden" defaultValue={process.env.REACT_APP_NOT_SECRET_CODE} />
</form>
</div>
);
}
I'm extracting some utility functions from my project into npm modules so I can use them in other projects.
Some of these functions rely on API Keys, and use different API Keys for DEV and PROD environments.
In the main project, this isn't a problem, as my build process sets the environment vars correctly, and my webpack build process results in the correct keys in the source code.
If I include the API Keys in the npm modules with the same DEV | PROD ternaries, will the environment vars of the main project work the same for the modules as they did for the code when it was in the main project?
// mymodule/index.js
export default function() {
return __PROD__ === true ? "abc" : "123"
// ....
}
// project/index.js in __DEV__ environment
import getKey from 'my-module'
getKey() // should return "123"
I may be misunderstanding your question, but what you're using aren't environment variables. They're probably variables you're filling in with Webpack's DefinePlugin, such as
new webpack.DefinePlugin({
__PROD__: true
})
When Webpack compiles your code, the plugin automatically replaces these magic global variables with the value in the configuration file.
The correct way to use an environment variable in node is process.env, as in process.env.__PROD__, and run your program with something like __PROD__=true node index.js, or by the more common convention NODE_ENV=production node index.js.
If you're publishing the compiled Webpack code to npm, then it should work with whatever DefinePlugin value you've set for the npm compile Webpack configuration.