问题
Suppose we have Angular 4+ app that needs to be located in different relative root URLs on different environments, i.e.:
http://localhost:4200/index.html
for developmenthttp://prod.server.com/angular-app/index.html
for production
Most likely, we'd want to have that option in our environment.x.ts
files:
export const environment = {
production: false,
appRoot: "/"
};
export const environment = {
production: true,
appRoot: "/angular-app/"
};
How can we configure Angular build/runtime infrastructure to automatically adjust the app depending on this option in environment.x.ts
files?
UPDATE:
Since I'm using the Angular CLI toolchain indirectly via Visual Studio build/publish system (template), it'd be nice to have a solution based completely on Angular CLI + *.json
/*.ts
/*.js
files. This way it would be suitable for any build system where Angular CLI could be used.
回答1:
If you are using the Angular CLI you can do:
ng build --prod --base-href /myUrl/
OR
ng build --prod --bh /myUrl/
回答2:
An alternative to the option described in @DeborahK answer could be to add build configurations to package.json
and setup your IDE to specify the desired build configuration depending on environment it's building for.
Here is a snippet from package.json
:
{
...
"scripts": {
...
"build": "ng build",
"build:Debug": "ng build --dev --base-href /",
"build:Release": "ng build --prod --base-href /angular-app/",
...
},
...
}
And here is a snippet of .csproj
file to give you an idea of how it could be integrated with Visual Studio (credits to @Andrey_Fomin in this discussion):
<Target Name="NgBuildAndAddToPublishOutput" AfterTargets="ComputeFilesToPublish">
<Exec Command="npm run | findstr "build:$(Configuration)"" ConsoleToMSBuild="true" IgnoreExitCode="true" EchoOff="true" WorkingDirectory="$(MSBuildProjectDirectory)">
<Output TaskParameter="ConsoleOutput" PropertyName="NpmScriptName" />
</Exec>
<Exec Condition=" '$(NpmScriptName)'=='build:$(Configuration)' " Command="npm run $(NpmScriptName)" />
<Exec Condition=" '$(NpmScriptName)'!='build:$(Configuration)' " Command="npm run build" />
</Target>
回答3:
UPDATED:
Carefully follow these steps and you are good to go :)
----------------------------------------------------------
1. Create 4 files in environment folder: (2 might there by default)
example:
environment.ts, environment.prod.ts,environment.test1.ts,environment.test2.ts
2. Use this common code for every file with slight change:
export const environment = {
production: true, //production is true for environment.prod.ts file
//for other test production is false
apiUrl: '' //base_url of each environment
};
3. Maintain a constant file where you will write all base urls.
code sample of constant.ts:
import { environment } from '../environments/environment';
let url = environment.apiUrl;
export const AppConstant = Object.freeze({
BASE_API_URL: url,
}
4. import this constant in your service or component class wherever your calling back-end.
5. In angular-cli.json:
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"test1": "environments/environment.test1.ts",
"test2": "environments/environment.test2.ts"
}
6.
ng build --env=prod
ng build --env=dev / ng build
ng build --env=test1
ng build --env=test2
7. if aot is creating problem. you can use : ng build --env=prod --no-aot
8. TO make things simple:
you can additonally add new build commands:
"scripts": {
"ng": "ng",
"start": "ng serve --env=local --no-aot",
"start:qa": "ng serve --env=dev --no-aot",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build:prod": "ng build --prod --env=prod --no-aot --output-hashing=all",
"build:dev": "ng build --prod --env=dev --no-aot --output-hashing=all",
"build:local": "ng build --env=local"
}
When you run,command is ==> npm run start OR npm run start:qa
OR==> npm run build:local or npm run build:dev, etc.
9. Hashing will solve caching isuue.
Hope it solves your problem. It works for me.
回答4:
In angular 6 we can do it in better way, by using environment.x.ts (x means it might be production/development/configuration etc files).
suppose if its dev mode file name(environment.dev.ts)
export const environment = {
production: false,
appRoot: "/" or appRoot: "http://somerestapi"
};
suppose if its in production mode file name(environment.prod.ts)
export const environment = {
production: true,
appRoot: "/" or appRoot: "http://somerestapi"
};
and same appRoot can be used in all services as in below service.ts file.
import { environment } from '../../environments/environment';
appRoot = environment.appRoot;
emplLoginCheckUrl = this.appRoot + "/checkValidUser";
validateUserDetails(employeeDetails): Observable<any> {
console.log(this.appRoot );
return this._httpClinet.post(this.emplLoginCheckUrl, employeeDetails);
}
after this we have one more job to do, its open your angular.json file
apply below changes to "dev": mode
"dev": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": true,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
and apply below changes to "production": mode
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
but you have to choose which one is needed to run the application, like if you want to run in dev mode use below command it will automatically apply appRoot(URL) for all aservices where you called.
ng build --configuration=dev (for development mode). ng build --configuration=production (for production mode).
来源:https://stackoverflow.com/questions/45970744/configure-base-url-depending-on-environment