I have 2 environment setup in my angular 6 web app.
Here I need to change the site logo depending on the environment.
The logo is returned from api. Depending on env how to run the api. And how to use this in components.
I implemented the static logo integration with env config by
environment.dev
production: true,
logourl: 'assets/images/logo.png',
environment.test
production: true,
logourl: 'assets/images/logo1.png',
Now the logo url is returned from api as
Dev: http://url.com/getlog?cliid=1
test: http://url.com/getlog?cliid=2
Where to run this api. If so how to configure this api response to env file.
Please help me to do this.
You just need to get reference to that environment variable in typescript and use binding to update logo source in HTML.
Typescript:
import { environment } from './../../../environments/environment.dev';
logoUrl: string;
constructor{
this.logoUrl= environment.logourl;
}
You can now bind logo url to HTML image like so:
<img [src]="logourl" />
Depending on your project setup, when you run Angular in prod, it should replace the import with the corresponding environment file.
When you generate a new project, Angular gives you environment.ts for development and environment.prod.ts for production.
You'd by default import environment in all your components and when you build project for production, Angular swaps the references to production.
Related
Problem Summary
Storybook snapshot test on static storybook returning blank screenshots even though they look fine on localhost:8080 when I ran npx http-server storybook-static
Tech stack and relevant code
Vue 3
Vite
Storybook
Jest
Storyshots
Puppeteer
I have components and their respective stories. npm run storybook works perfectly fine. My storybook.spec.js is as follows:
import { imageSnapshot } from "#storybook/addon-storyshots-puppeteer"
import initStoryshots from "#storybook/addon-storyshots"
initStoryshots({
suite: "Image storyshots",
test: imageSnapshot(
storybookUrl: 'file://absolute/path/to/my/storybook-static'
)
})
I ran the following. fyi, I did not modify any file in storybook-static after running npm run build-storybook.
npm run build-storybook
npm run test
npm run test constitutes jest --config=jest.config.js test
Problem
Unfortunately, the screenshots I get are all blank and fail the snapshot test.
I suspect it might be due to a CORS error just like other Storybook users when they click <project-root>/storybook-static/index.html after running npm run build-storybook, to which I want to ask for a solution as well, because I wanna run test remotely on a headless server.
Note
I used absolute path because relative path caused a resource not found error during the testing process.
The problem is that you're running the tests from file:// instead of http://. So the URI is file:// and the img url ends up like this after applying some url logic: path.resolve(window.location, '/your-image.png') file:///your-image.png.
If this is the case you could change to http://. You can start a express server and serve the storybook-static folder from setupGlobal and then shut it down in teardownGlobal. Then you will need to change your storybookUrl to http://localhost:<some-port>.
None of the images were loading within my pipeline but worked fine locally, ended up being because the components were fetching images using a relative path <img src="/my-image" /> which apparently is not allowed using the file protocol.
I ended up doing 2 things:
Updating the static dirs directory to use the root by updating the main.js file in storybook
module.exports = {
staticDirs: [{ from: '../static', to: '/' }],
}
Added a script to remove the leading slash of images in the preview-head.html file from storybook
<script>
document.addEventListener('DOMContentLoaded', () => {
Array.from(document.querySelectorAll('img')).forEach((img) => {
const original = img.getAttribute('src');
img.setAttribute('src', original.replace('/', ''));
});
});
</script>
Another (arguably better) approach would be to run the tests through a server where you can access the images
I am using firebase authentication in my nextjs app. I have stored my service account credentials in a file called secret.json. I wanna hide those credentials in my next.config.js file. How can I access those credentials in the secret.json file? Maybe this will be the same approach not only for nextjs apps but also for other apps. What is the common way to achieve that or is there any specific way for nextjs app?
You might consider storing your private key as an environment variable, which Next.js has built-in support for. You can then avoid the risks of exposing your secrets in next.config.js and services like Heroku and Vercel make it easy & secure to store your env vars in production.
To initialize Firebase on your server, you need just 3 things from your secret.json file:
project_id
client_email
private_key - store this as an env var (e.g., FIRESTORE_PRIVATE_KEY)
You can then use the firebase-admin package to initialize Firebase on your server:
import { cert, initializeApp } from 'firebase-admin/app'
const serviceAccount = {
projectId: 'my-project',
clientEmail: 'myServiceAccount#my-project.iam.gserviceaccount.com',
privateKey: process.env.FIRESTORE_PRIVATE_KEY,
}
const credential = cert(serviceAccount)
initializeApp({ credential })
Saving the private_key as its own env var will also avoid problems arising from attempting to save/parse the entire Firestore json as an env var (e.g., ENAMETOOLONG error) and not require you to do any string manipulation.
Referring to official NestJS documentation, it is recommended to use ConfigService in order to use environment variables.
So in the code, we access all vars defined in an .env file with something like:
config.get('PORT')
But it is not recommended to use .env in production environment. So how to deploy in that way?
Why not just use the standard method with dotenv and process.env.PORT?
There are two problems that make the ConfigService less useful.
First
When no .env file is present in any environment, readFileSync in
dotenv.parse(fs.readFileSync(filePath))
will fail:
[Nest] 63403 [ExceptionHandler] path must be a string or Buffer
TypeError: path must be a string or Buffer
at Object.fs.openSync (fs.js:646:18)
at Object.fs.readFileSync (fs.js:551:33)
at new ConfigService (../config/config.service.ts:8:38)
Even if e.g. process.env.API_KEY is available
this.configService.get('API_KEY')
will not return anything. So the ConfigService forces you to use a prod.env file, which dotenv advocates against:
No. We strongly recommend against having a "main" .env file and an
"environment" .env file like .env.test. Your config should vary
between deploys, and you should not be sharing values between
environments.
https://github.com/motdotla/dotenv#should-i-have-multiple-env-files
Second
You have to import the config module and inject the service in order to use it. When you use env variables like this
imports: [
MongooseModule.forRoot(process.env.MONGO_URI, { useNewUrlParser: true }),
ConfigModule,
],
the config service is useless.
Read more about config in the environment here: https://12factor.net/config
But this is not recommended to use .env in production environnement. So how to deploy that way ?
Actually, it is not recommended to commit your .env files. It's perfectly fine to use them in production :-).
Why not use the standard method with dotenv and process.env.PORT?
It allows decoupling your core code from the code responsible for providing configuration data. Thus:
The core code is easier to test: doing some manual changes/mocking of process.env is such - a - pain, whereas mocking a "ConfigService" is pretty easy
You can imagine using anything else than environment variables in the future by just replacing a single method (or a few getters) in a dedicated class, instead of replacing all the occurrences of process.env.* in your code // to be fair, this is unlikely to happen, as using env. variables is the most common way to load configuration data, but still.
Using #nestjs/config (a.k.a. ConfigModule) makes environment variables available to your app whether they come from a .env file or set in the environment. Locally you use a .env file and on production use the environment.
I have my page configuration done via JCR configuration.
I have the component configuration using YAML configuration.
I want to make this component available to the a template configured in the JCR.
The component config is under: /project-website-module/src/main/resources/website-module/components/linkList/linkList.yaml
I tried to reference this in the template's component availability in different ways:
website-module:components/linkList/linkList
website-module:components/linkList/linkList.yaml
/website-module/components/linkList/linkList
/website-module/components/linkList/linkList.yaml
src/main/resources/website-module/components/linkList/linkList
src/main/resources/website-module/components/linkList/linkList.yaml
But no luck, I keep getting the error:
"Caused by: info.magnolia.config.registry.Registry$NoSuchDefinitionException: <pathToComponentConfiguration>"
The component config is under:
/project-website-module/src/main/resources/website-module/dialogs/linkList/linkList.yaml
... that's the dialog config, where's the component config yaml?
Path to the component config not to dialog config is the one that you need to use when referring to the component. And that config file needs to be physically at src/main/resources/website-module/templates/components/... and reference is then website-module:components/....
Also if you have specified module descriptor for the module, name in the module descriptor better match the website-module.
I had to move the YAML component configuration under (notice the templates directory added):
/project-website-module/src/main/resources/website-module/templates
In my case, move linkList.yaml under:
/project-website-module/src/main/resources/website-module/templates/components/linkList/linkList.yaml
Then in the JCR config, use the following path:
website-module:components/linkList/linkList
Note: likewise, YAML dialog configurations must be under:
/project-website-module/src/main/resources/website-module/dialogs
I have ASP.NET Core application (Web Api). The documentation has explained working with multiple environments, however it failed to explain how to set aspnetcore_environment when publishing the web site.
So lets say if i have 3 environments Development, Staging and Production
In classic ASP.NET Web Application i used to create 3 build configurations. Development, Staging and Production ( Like shown in picture below). and then 3 .pubxml files, one for each configuration. Do i need to use the same approach for ASP.NET Core application as well?
How do i set aspnetcore_environment in .pubxml file?
If the approach specified in Question 1 is obsolete, then what's the alternate approach? ( I use Jenkins for CI)
Update 1
I understand that I have to set ASPNETCORE_ENVIRONMENT however I am not able to understand where do we set this? During development I can set this in profile in launchSettings.json, however question was how do we set this when publishing to staging or production? do we set environment variable on the target server itself?
Update 2
I found article here that explains different ways of setting environment variable. This partially answered my question. However when I publish the application, the publish process does not honor the environment variable while publishing appsettings.{env.EnvironmentName}.json
I have created separate post for that question
You could pass in the desired ASPNETCORE_ENVIRONMENT into the dotnet publish command as an argument using:
/p:EnvironmentName=Staging
e.g.
dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging
This will generate out the web.config with the correct environment specified for your project:
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>
I had the same requirement, and I came up with the following solutions. This works well with automated deployments and require fewer configuration changes.
1. Modifying the project file (.CsProj) file
MSBuild supports the EnvironmentName Property which can help to set the right environment variable as per the Environment you wish to Deploy. The environment name would be added in the web.config during the Publish phase.
Simply open the project file (*.csProj) and add the following XML.
<!-- Custom Property Group added to add the Environment name during publish
The EnvironmentName property is used during the publish for the Environment variable in web.config
-->
<PropertyGroup Condition=" '$(Configuration)' == '' Or '$(Configuration)' == 'Debug'">
<EnvironmentName>Development</EnvironmentName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != '' AND '$(Configuration)' != 'Debug' ">
<EnvironmentName>'$(Configuration)'</EnvironmentName>
</PropertyGroup>
Above code would add the environment name as Development for empty or Debug configuration. For any other Configuration the Environment name would be picked from the configuration which was selected. This will add the ASPNETCORE_ENVIRONMENT environment with the desired configuration. You can modify the logic for environment name as desired by updating the CsProj file. More details here
2. Adding the EnvironmentName Property in the publish profiles.
We can add the <EnvironmentName> property in the publish profile as well. Open the publish profile file which is located at the Properties/PublishProfiles/{profilename.pubxml} This will set the Environment name in web.config when the project is published. More Details here
<PropertyGroup>
<EnvironmentName>Development</EnvironmentName>
</PropertyGroup>
As shown in above image, environment can be added for each configuration and the name of the EnvironmentName property can be changed in each *.pubxml file.
3. Command line options using dotnet publish
Additionaly, we can pass the property EnvironmentName as a command line option to the dotnet publish command. Following command would include the environment variable as Development in the web.config file.
dotnet publish -c Debug -r win-x64 /p:EnvironmentName=Development
When hosting the application under IIS you can set the environment variable in web.config.
https://learn.microsoft.com/en-us/aspnet/core/hosting/aspnet-core-module
To generate it on publish add a web.config to the root of your project, "dotnet publish" will use this file as the basis for the one that is generated for in the publish folder. Then you can change the value in your deployment system.
<?xml version="1.0" encoding="utf-8" ?>
<!-- Used to overwrite settings web.config generated by "dotnet publish", Only used when hosting under IIS -->
<configuration>
<system.webServer>
<aspNetCore stdoutLogEnabled="true">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>
I think you can't do it in the publish profile. You have to set environment variable, e.g. ASPNETCORE_ENVIRONMENT = Staging.
I had to do a similar thing with a aspnet core web app on Azure. I wanted to have dev, staging and production. The way I did it was exactly with env variable.
To setup two or more profiles, you need to create additional profile, as mentioned in a linked article, and your launchSettings.json will contain an array:
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express (Staging)": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Staging"
}
}
}
To be able to read the environment variable, you need to specify it during startup and call additional method AddEnvironmentVariables to variables take action:
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
// general properties
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
// specify the environment-based properties
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
// do not forget to add environment variables to your config!
.AddEnvironmentVariables();
Configuration = builder.Build();
}
}
Simple way to set it in visual studio IDE.
Project > Properties> Debug > Environment variables
Please do not use environment variables of machine level instead scope
to the application , there is a possibility of other application doing
same, changing may affect other application.