问题
I have an angular 9 project which is part of an application suite installer [Wix installer]. One of the settings used by the angular app is the address of API which it fetches its data from some configurable address. I know that I can have many angular environment files and simply use commands such as the followings:
environment.env1.ts
export const environment = {
production: true,
apiAddress: "http://apiAddress1/api/",
};
ng build --prod --configuration=env1
or
environment.env2.ts
export const environment = {
production: true,
apiAddress: "http://apiAddress2/api/",
};
ng build --prod --configuration=env2
This means for every potential API address I need to do a new build and run above command. How can I overcome above scenario and configure output binaries after the build?
Assuming there is no clear way of achieving the after-built configuration, can I do 'simple string replace' for the address of API in the generated main*.js files? Would there be any side effects?
回答1:
You can outsource your api endpoint in a config file. And provide an AppInitializer
to use your config file.
Here is an example:
the loader function, which loads the config via http from /config/config.json
and sets the api configuration:
export function loadConfig(http: HttpClient, config: ApiConfiguration): (() => Promise<boolean>) {
return (): Promise<boolean> => {
return new Promise<boolean>((resolve: (a: boolean) => void): void => {
http.get('./config/config.json')
.pipe(
map((x: any) => {
config.rootUrl = x.rootUrl + '/v2';
resolve(true);
}),
catchError((x: { status: number }, caught: Observable<void>): ObservableInput<{}> => {
// 404 local development, other errors are strange
resolve(x.status === 404);
return of({});
})
).subscribe();
});
};
}
The json contains only one string named rootUrl
.
And to use this function, before the app initializes, provide an AppInitializer
in your app.module.ts
:
providers: [
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [
HttpClient,
ApiConfiguration
],
multi: true
}
ApiConfiguration
stores the api endpoint which is just a class with a default value (for devlopment):
@Injectable({
providedIn: 'root',
})
export class ApiConfiguration {
rootUrl: string = 'localhost:8080';
}
Just put a config file in your /dist
folder and it should work :)
回答2:
It is probably possible to perform a find and replace on the generated files after the build completes, but that just feels wrong.
Instead create a configuration.json file and put it in your assets folder. Then in your application, reference the file directly by using an import. You might have to enable this functionality by setting resolveJsonModule
to true
in your tsconfig.json.
Now, after the application is built, the value can be replaced in configuration.json without fear of unintended side effects by using simple techniques such as in NodeJs with fs.readFileSync(path)
and fs.writeFileSync(path, JSON.stringify(data))
.
Sample xyz.module.ts section
import dynamicConfig from '../assets/configuration.json';
@NgModule({
providers: [
{
provide: API_BASE_URL,
useValue: dynamicConfig.apiAddress
}
]
})
export class XyzModule { }
来源:https://stackoverflow.com/questions/61877574/configuring-angular-production-files-after-build