Replace .env file after build
ScorprocS opened this issue ยท 6 comments
Hello I didn't know where to ask the question so sorry for creating an issue for that.
I would like to replace the .env file on runtime to be able to use the same build for all environments (AAT, PROD) but I don't know how to do it. And I didn't found anything in doc about that.
I'm using DotenvRunPlugin and the angular build is directly deployed in /html folder of nginx.
Here's my actual configuration.
Angular.json
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.config.js"
},
./webpack.config.js
var BrotliPlugin = require('brotli-webpack-plugin');
//const { AngularCompilerPlugin } = require('@ngtools/webpack');
const CompressionPlugin = require('compression-webpack-plugin');
const path = require(`path`);
const { DotenvRunPlugin } = require("@dotenv-run/webpack");
module.exports = {
plugins: [
new BrotliPlugin({
// ...
}),
new CompressionPlugin({
// ...
}),
new DotenvRunPlugin({
prefix: /^APP|NG/,
verbose: true,
root: "../../src/" ,
files: ['.env'],
dotenv: { override: true },
}),
]
}
Thanks in advance for your help
Hello,
You cannot achieve what you want.
The plugin replaces process.env / import.meta.env notations in your code source with the values in your environment (including those read from you .env) at build time.
Let's say you put import.meta.env.API_URL in your code, when you build your app using the plugin, it is replaced by the value in process.env.API_URL let's say localhost:3000, so in your JS chunk there will only be localhost:3000
If you want different values (different environment), you'd have to build the app with that specific environment.
Hello, You cannot achieve what you want. The plugin replaces process.env / import.meta.env notations in your code source with the values in your environment (including those read from you .env) at build time. Let's say you put import.meta.env.API_URL in your code, when you build your app using the plugin, it is replaced by the value in process.env.API_URL let's say localhost:3000, so in your JS chunk there will only be localhost:3000 If you want different values (different environment), you'd have to build the app with that specific environment.
Hello thanks for your reply.
ok. But it must be possible for instance I could put the .env file in asset folder or create an env.js file with all constants and replace them when I want to change the environment. But I would like to do it properly and safely.
For instance I've found thoses solutions:
- environment-variables-angular-docker
- https://www.technouz.com/5125/changing-angular-environment-variables-at-runtime/
- https://imran3.medium.com/runtime-configuration-for-angular-c9d9082e1de3
- https://totheroot.io/article/runtime-environments-in-angular-and-why-they-matter
Are you sure that I cannot achieve that with the dotenv-run library (which I found awsome and really easy to use) ? I didn't want to do something boilerplate.
I get your point.
The current implementation does not permit it for sure.
But that could be nice feature indeed.
What would be the best developer experience in your opinion?
Thanks.
I think the best would be able to use only a .env file which will be injected at build time for default and common values (as it is now) and give a way to override those variables at run time by replacing the .env.runtime file (or custom named file) in the assets folder. And add a provider to replace the overrided env variable.
On your side the implementation could be done on angular startup:
providers: [
{
provide: APP_INITIALIZER,
useFactory: initConfig,
deps: [AppConfigService],
multi: true,
},
],
In the configService you could fetch all env vars defined in .env.runtime to replace them.
could be done like :
const result = dotenv.config({ debug: true,override: true, path: 'custom/path/to/.env' });
I don't know if this approach could be compatible with other framework.
In any case thanks a lot for your concern.
I've published a new version of the package in alpha supporting runtime environment variables.
I'd appreciate if you can give it a try.
npx ng add @ngx-env/builder
Set the runtime
option to true in angular.json
"scripts": [],
"ngxEnv": {
"runtime": true
},
Usual way to use environment variables in code
title = import.meta.env.NG_APP_VERSION;
NG_APP_VERSION=10.0.0 npm run build
The application can be served from the dist/<app-name> folder.
Inside the dist/<app-name> folder, a new ngx-env.js
file is generated:
globalThis._NGX_ENV_ = {
NG_APP_VERSION: "10.0.0",
};
You can modify it and reload the window.
If you're using SSR, add import '@ngx-env/builder/runtime';
to the top of the main.server.ts
file.
Added experimental runtime support in 17.3.0.