Access system variable (Environment Variable) while building Angular 2 application - javascript

I need to build my Angular application using one system variable.
System Variable
server_url = http://google.com
My Environment.ts file look like
export const environment = {
production: false,
serveUrl: 'http://someurl.com',
mleServerUrl: 'http://someurl2.com',
botServerUrl: 'http://someurl2.com',
DEBUG_LOG: true,
azureAD: true,
mleEnvironment: 'dev',
multtenant: true,
e2eTest: false
};
I need to replace serveUrl value with http://google.com while executing ng build command.

You need a environment.prod.ts (in the same folder as environment.ts) with
export const environment = {
production: true,
serveUrl: 'http://google.com',
};
then you have to do a ng build --prod
See https://github.com/angular/angular-cli/wiki/build

If you want to use system environment variables instead of the standard angular approach here are a few options:
Create a env service that is available through your Angular app; leverages a env.js file which can be modified at deploy time. https://www.jvandemo.com/how-to-use-environment-variables-to-configure-your-angular-application-without-a-rebuild/
Modify your webpack process with a custom angular build which allows you to read system environment variables at build time https://blog.usejournal.com/system-environment-variables-in-angular-1f4a922c7b4c

Related

How to pass variables from Azure Pipeline to JavaScript?

I'm attempting to run an Azure Pipeline, with some environment variables defined in the pipeline itself, and I am using the Maven Build task to build my project with Maven to launch various tests. A JS file automatically runs before each test, and I'm supposed to configure these variables in this file, which would make them available to use in the tests themselves. Currently, I have something like this:
# azure-pipelines.yml
trigger:
- none
pool:
vmImage: ubuntu-latest
variables:
- name: user_secret
value: "foo"
steps:
- task: Maven#3
inputs:
mavenPomFile: 'pom.xml'
goals: test
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
javaHomeOption: 'JDKVersion'
mavenVersionOption: 'Default'
mavenAuthenticateFeed: false
effectivePomSkip: false
sonarQubeRunAnalysis: false
// config.js
function fn(){
return {
secret: user_secret
};
}
The error I get is "user_secret" is not defined
I am being told I can debug it locally because the pipeline is providing the values as environment variables, and that I should be able to validate that locally by setting the variables when I run my code. Unfortunately, I can't figure out how to do it.
Similar to the above example, I also tried to get the variable process.env.user_secret, but this didn't work for me either.
How can I access Azure variables in my code?

Change .page URL based on environment I need to run the suite in

We have been building our automation suite using our staging environment, but are going live soon and want to be ready to tell the project where to run (staging, production).
The only difference between the sites in the environments is the URL. My question is, from start to finish, how can I set the .page URL via a CLI option?
Right now, I have created an environment config file that holds our staging and production URLS and then I call the data into my test files. This is fine for now, but I will need to create a script with an option to set the environment at runtime without having to do a manual find and replace before kicking it off.
I've looked around online and find, what I believe, to be code snippets and general instructions, but I'm not a dev at heart and go crossed eyed. If I could get an ELI5 for this, that would be awesome.
Example of what I'm doing now:
const env = require('../environment_variables.json')
fixture `blog`
.page `${env.production}`
And then I change production to staging or vice versa manually before kicking off the suite.
Since the project will run from CICD, I would like to be able to do something like this in my CLI and script:
testcafe env=production
The env value will then be set where the .page call is for every test file.
Thanks!
There are different ways of doing this. I've used environment variables successfully in this situation, so I'll share this solution since it will solve your problem.
I create config.json in the root of the project:
{
"baseUrl": {
"dev": "https://dev.com/",
"staging": "https://staging.com/",
"prod": "https://prod.com/"
}
}
Then I create two helper functions somewhere like Helpers/env.js:
import config from '../config';
function getEnv () {
return process.env.TESTCAFE_ENV;
}
function getBaseUrl () {
return config.baseUrl[getEnv()];
}
export { getEnv, getBaseUrl };
Then in my test files in Tests/:
import { getBaseUrl } from '../Helpers/env';
const baseUrl = getBaseUrl();
fixture `Test Suite`
.page(baseUrl);
And that's it. Then when I need to run tests on the dev, I execute:
$ TESTCAFE_ENV=dev testcafe
for staging:
$ TESTCAFE_ENV=staging testcafe
and for production:
$ TESTCAFE_ENV=prod testcafe
In v1.20.0 and later, TestCafe offers a way to specify the baseUrl in the test run configuration. You can use this approach along with environment variables, see the following example:
.testcaferc.js
const BASE_URL_MAP = {
dev: 'https://dev.com/',
staging: 'https://staging.com/',
prod: 'https://prod.com/'
};
module.exports = {
baseUrl: BASE_URL_MAP[process.env.TESTCAFE_ENV]
};
Alternatively, you can use different configuration files for each of the required setups using the --config-file option.

next.js environment variables are undefined (Next.js 10.0.5)

I am coding a website with Next.js and I tried to add google Tag Manager.
I followed the tutorial on the Next.js Github example but for some reasons I can't access to my environment variables.
It says my variable is undefined.
I created a file .env.local on my project folder (at the same level as components, node_modules, pages, etc)
In this file I created a variable like this (test purpose) :
NEXT_PUBLIC_DB_HOST=localhost
And on my index page I tried this code :
console.log("test ", process.env.NEXT_PUBLIC_DB_HOST);
But in my console I get a "test undefined".
I tried to put my variable into an .env file instead, without success.
What I am doing wrong ?
This envs just works in Server Side. To access this envs in Client Side, you need declare in the next.config.js
This way:
module.exports = {
reactStrictMode: true,
env: {
BASE_URL: process.env.BASE_URL,
}
}
Create .env (all environments), .env.development (development environment), and .env.production (production environment).
Add the prefix NEXT_PUBLIC to all of your environment variables.
NEXT_PUBLIC_API_URL=http://localhost:3000/
Use with prefix process.env
process.env.NEXT_PUBLIC_API_URL
Stop the server and restart it:
npm run dev
I hope it works.
This solution for latest version of nextJs (above 9)
Restarting the server worked for me.
Edit & save .env.local
Stop the server and restart it, npm run dev
You should get an output on the next line like this:
> klout#0.1.0 dev
> next dev
Loaded env from [path]/.env.local
For those using NextJS +9 and looking for environment variables in the browser, you should use the NEXT_PUBLIC_ prefix. Example:
NEXT_PUBLIC_ANALYTICS_ID=123456789
See documentation for reference.
After spending countless hours on this, I found that there is a tiny little paragraph in both the pre and post nextjs 9.4 documentation:
(Pre-9.4) https://nextjs.org/docs/api-reference/next.config.js/environment-variables (same as this answer)
Next.js will replace process.env.customKey with 'my-value' at build time.
(^9.4) https://nextjs.org/docs/basic-features/environment-variables
In order to keep server-only secrets safe, Next.js replaces process.env.* with the correct values at build time.
Key words being BUILD TIME. This means you must have set these variables when running next build and not (just) at next start to be available for the client side to access these variables.
This is my next.config.js file.
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
env: {
BASE_URL: process.env.NEXT_PUBLIC_SITE_URL,
},
};
module.exports = nextConfig;
Restart the server and it worked fine. using Nextjs 12.1.0 with typescript
In my case, Im pasting REACT_APP_API_URL instead of NEXT_PUBLIC_API_URL.
Adding with the most recent version of the documentation on this, v12+.
Using the next.config.js file you can specify server and client variables:
module.exports = {
serverRuntimeConfig: {
// Will only be available on the server side
mySecret: 'secret',
secondSecret: process.env.SECOND_SECRET, // Pass through env variables
},
publicRuntimeConfig: {
// Will be available on both server and client
staticFolder: '/static',
},
}
You can still use an env.local file, and pass the variable in to the next.config.js file. For example:
publicRuntimeConfig: {
DB_URL: process.env.DB_URL
}
And then you can access the variable like this:
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
publicRuntimeConfig.DB_URL;

Load a variable from dotenv file when starting PM2

I am starting instances of my app as a package.json script with PM2 this way:
"start:pm2": "pm2 start -i max node myapp.js"
I found out that not all members in the team always want to use max as a value for instances number while developing, but prefer to use some lower value.
To not change package.json I would better let them change the value inside .env file because we already use it so that the value from it would be used as the parameter to pm2.
I know I can create a wrapper js or bash script to load the variable from .env file and pass it to pm2 but it would be better to have a solution without it.
How can I achieve this?
You can create an ecosystem.config.js file and declare your environment variables under the “env:” attribute, in your case the NODE_APP_INSTANCE can be used to set the number of instances:
module.exports = {
apps : [{
name: "MyApp",
script: "./myapp.js",
env: {
NODE_ENV: "development",
NODE_APP_INSTANCE: "max"
},
env_production: {
NODE_ENV: "production",
}
}]
}
Then call pm2 start or pm2 start /path/to/ecosystem.config.js to load an ecosystem from an other folder.
A better pattern here is to remove dotenv from your code and "require" it on the command line. This makes your code nicely transportable between any environment (including cloud-based) - which is one of the main features of environment variables.
a) code up your .env file alongside your script (e.g. app.js)
b) to run your script without pm2:
node -r dotenv/config app.js
c) in pm2.config.js:
module.exports = {
apps : [{
name : 'My Application',
script : 'app.js',
node_args : '-r dotenv/config',
...
}],
}
and then
pm2 start pm2.config.js
Note: the use of dotenv/config on the command line is one of the best practices recommended by dotenv themselves

Angular 4 create assets / files per environment?

We use environment variables within our angular app to read settings etc but is there a way to generate assets/files on build?
Basically we'd like to create an 'auth/settings.js' file in the assets folder containing client id's and apiUrl's unique to each environment. These will be used in the index.html (so outside of the angular app bootstrap )
e.g. the values in the environment.ts exported into a js / json file output to the assets folder so they can be read in index.html
export const environment = {
production: false,
title: 'default',
clientId: 'xxxx-xxxx-xxxx-xxxx-xxxx',
clientUrl: 'https://localhost:4200/app',
apiUrl: 'https://localhost/api'
};
I have read that you can use mulitapps:
https://github.com/angular/angular-cli/wiki/stories-multiple-apps
This may work but looks like a lot of copy and pasting and we'll have quite a few versions of the build - I'm not sure if you can declare the common settings once and just extend the extra app settings (inheritance)?
Thanks
What we are doing in our case is actually having an config.json and config.[env-name].json files in app/config folder that configured in project assets. The config.json file is getting fetched before angular bootstrap using browser Fetch API
On our build server we are just replacing the content of config.json withconfig.staging.json or config.prod.json based on environment build. Also we have AppSettings class that gets created on bootstrap. Here is how it is looks like:
fetch(configUrl, { method: 'get' })
.then((response) => {
response.json()
.then((data: any) => {
if (environment.production) {
enableProdMode();
};
platformBrowserDynamic([{ provide: AppSettings, useValue: new AppSettings(data.config) }]).bootstrapModule(AppModule);
});
});
UPDATE:
If you need to stick some values based on your env in to index.html you might need to consider doing that on your build server. You can rather string replace the values or you can have index.[env-name].thml files so you just overwrite the index.html based on environment build.
Also check out this issues
- https://github.com/angular/angular-cli/issues/7506
- https://github.com/angular/angular-cli/issues/3855

Categories