1

I have experience on Jquery but Angular is very new to me and so is spartacus. I have been trying to configure our Spartacus to be used across multiple environments. The only solution that I could find was to use the meta tag on index.html and then grab the config based on url as mentioned by janwidmer and CarlEricLavoie. I did make a slight change from these 2 solutions though, and that was to use the environment.{env}.ts files instead of a new Backend service or keeping the config in a map in the same file.

The issue that I am facing is that the spartacus.cofniguration.module.ts file needs these values in @NgModule and I've tried everything that I could think of, but am unable to use the value of this.config.backend?.occ?.baseUrl inside the NgModule, where I need to give the value for base URL and Base site.

Below is what I am trying to do. i have written the logic that would expose the correct config object according to the OCC base url that I receive on the environment. Now over here, the console log inside the constructor prints a proper object with all the properties I need, but then the conf object right before the @NgModule, it prints undefined and the values inside the NgModule are undefined as well then.

I also tried to create a new class and import it here so I could maybe create an instance, but couldn't do that as well, as it would then need the variable/method to be static for me to be able to access it inside NgModule.

import { Injectable, NgModule } from '@angular/core'; 
import { FacetChangedEvent, FeaturesConfig, I18nConfig, OccConfig, provideConfig, SiteContextConfig } from "@spartacus/core";
import { environment } from '../../environments/environment';
import { defaultB2bCheckoutConfig, defaultB2bOccConfig } from "@spartacus/setup";
import { defaultCmsContentProviders, layoutConfig, mediaConfig } from "@spartacus/storefront";
import { translations } from 'src/assets/i18n-translations/translations';
import { translationChunksConfig } from 'src/assets/i18n-translations/translation-chunks-config';
import { CdcConfig, CdcRootModule, CDC_FEATURE } from '@spartacus/cdc/root';
import { EnvironmentConfigurationModule } from "../../environments/environment-configuration.module"
import { environment  as envdev} from '../../environments/environment';
import { environment as envstag} from '../../environments/environment.stage';
import { environment as envprod} from '../../environments/environment.prod';

let conf : any;
console.log("before ng");
console.log(conf);

@NgModule({
  declarations: [],
  imports: [
  ],
  providers: [provideConfig(layoutConfig), provideConfig(mediaConfig), ...defaultCmsContentProviders, provideConfig(<OccConfig><unknown>{
    
      backend: {
        occ: {
          baseUrl: environment.baseUrl,
        }
      },
    }), provideConfig(<SiteContextConfig>{
    context: {
      urlParameters: ['baseSite', 'language', 'currency'],
      baseSite: [environment?.baseSite],
      currency: ['USD', 'GBP',]
    },
  }),
  provideConfig(<I18nConfig>{
    i18n: {
      backend:{
        loadPath:'assets/i18n-translations/{{lng}}/{{ns}}.ts',
      },
      resources: translations,
      chunks: translationChunksConfig
      ,fallbackLang: 'en'
    },
  }
  ), provideConfig(<FeaturesConfig>{
    features: {
      level: '4.2'
    }
  }), 
  provideConfig(defaultB2bOccConfig), provideConfig(defaultB2bCheckoutConfig), 
]
})
export class SpartacusConfigurationModule { 
  urlValue : string | undefined; 
  env: any;

  constructor(private config: OccConfig) {
        
    this.urlValue = this.config.backend?.occ?.baseUrl;
    
    console.log("baseurl : " + this.config.backend?.occ?.baseUrl);
    
    if(this.urlValue?.includes('s1'))
    { 
      this.env=envstag;   
    }
    else if(this.urlValue?.includes('p1'))
    {
      this.env=envprod; 
    }
    else{
      this.env=envdev; 
    } 
    conf = this.env;
    console.log("conf");
    console.log(conf);
    }

  getConfig() {
   return conf;
  }
}

Apart from these solutions, we have also tried to use window.location and location.href to find the base url and work based on that. This works amazing on local, but as soon as you deploy it to the server, it says that the reference window not found/reference location not found. We tried to do this right before the NgModule, inside spartacus-configuration.module.ts

import { environment as envDev } from "../../environments/environment";
import { environment as envStage } from "../../environments/environment.stage";
import { environment as envProd } from "../../environments/environment.prod";
 
let loc=location.hostname;
let env;
if(loc.includes('s1'))
{ 
  env=envStage;   
}
else if(loc.includes('p1'))
{
  env=envProd; 
}
else{
  env=envDev; 
}  
console.log("before ng===>>>",loc); 

1 Answers1

0

With environment imports, your standard build configuration will replace the environment.ts variables with the ones set by your server's environment (eg. process.env) before deployment. Therefore, you should only import from environment.ts in your code and let the server handle overriding the staging environment variables.

With location and window objects, they are not accessible on the server-side of the build because Angular Universal initially delivers a pre-rendered page readable by bots (usually html-only) for SEO purposes. The location and window objects do not exist in this instance. In Angular, window and location objects should be imported into your classes.

Use Window: https://stackoverflow.com/a/52620181/12566149

Use Location: https://stackoverflow.com/a/43093554/12566149

Caine Rotherham
  • 306
  • 1
  • 5
  • Thanks Caine. So do you mean that the OCC url will be set on the environment.ts file on the server and I don't need to put any conditions to find the correct file? If yes, then the only issue would be that I think it's only the occ url that can be configured on index.html but not all the properties that we need configured per environment. In our case, it would be Gigya API key, etc. How can we configure them per environment? – Pranav Bhartia Mar 06 '22 at 21:56
  • Just as an example, in your `environment`/`environment.prod.ts` files, you can set an environment variable like `export const environment: Environment = { gigyaKey: process.env.GIGYA_KEY };`. The `process.env.GIGYA_KEY` is set by the environment that the build server runs on and can be accessed in the app by importing the `environment` object. eg. `environment.gigyaKey`. – Caine Rotherham Mar 07 '22 at 07:03
  • I just gave it a go. Picked up a random property form Commerce cloud server and added it on the meta tag's content. Deployed the changes, but the value of the content still has the key in it, instead of the value. What would be the way to add properties to the environment for this? – Pranav Bhartia Mar 08 '22 at 01:09