angular - How to dynamically change the content in

2020-07-16 02:31发布

问题:

I want to change the URL of a script tag when I'm running the ng build command with the --prod option and without the --prod option. Following is an example.

ng build --prod

<!DOCTYPE html>
<html>
<head>
    <title>Home Page</title>
</head>
<body>
    <script src="https://my-site.net/prod.js"></script>
</body>
</html>

ng build

<!DOCTYPE html>
<html>
<head>
    <title>Home Page</title>
</head>
<body>
    <script src="https://my-site.net/dev.js"></script>
</body>
</html>

How can I achieve this?

回答1:

For current versions of Angular from v6.1.0-beta.2 on, you can use the fileReplacements value in the angular.json file configurations as detailed in this answer: https://stackoverflow.com/a/57274333/228429 by @massic80.

More info here: https://github.com/angular/angular-cli/issues/4451#issuecomment-395651237

For older versions before v6.1.0-beta.2, Angular CLI does not provide any such feature. But you can use environment variables to inject proper scripts dynamically on run time.

Eg:

main.ts

import { env } from './environments/environment';

if (env.production) {
   const script = document.createElement('script');
   script.src = https://my-site.net/prod.js
   document.head.appendChild(script);
} else {
   const script = document.createElement('script');
   script.src = https://my-site.net/dev.js
   document.head.appendChild(script);
}

Read more here: https://github.com/angular/angular-cli/issues/4451#issuecomment-285329985



回答2:

In angular.json you can configure the index file to be used (I'm using Angular 8):

"projects": {
    "projectName": {
        "architect": {
            "build": {
                "options": {
                    "index": "src/index.html", // this is the default location (also for ng serve)
                    "configurations": {
                        "production": {
                            "index": "index-prod.html" // this is the prod version (you can also link it to /prod/index.html or whatever: it will be placed in the dist root folder with the provided name)
                        },
                        "development": {
                            "index": "index-whatever.html" // this is the version for ng build --configuration=development`
                        }
                    }
                }
            }/*, UPDATED: THIS DOESN'T WORK
            "serve": {
                "index": "dev/index.html" // file to be used in ng serve
            }*/
        }
    }
}

AFAIK none of those "index"s is mandatory, except the first

Sidenote: this is what I just tried with some tries, builds and ng serves. I didn't find it in any documentation.

Check it out and let me know.

===========

UPDATE 19 Oct '19: I noticed that the configuration reported above still uses src/index.html also for serve on "@angular/cli": "^8.3.6", "@angular/compiler-cli": "^8.2.8". Looks like there is no override for serve itself. My question is: should serve always inherit base index configuration?

Trying to dig a bit more I found this: https://github.com/angular/angular-cli/issues/14599

There is an example of how it should work with the new CLI, but attempting to replace the

"development": {
    index": "index-whatever.html"
}

with a

"development": {
    index": {
        "input": "index-whatever.html"
    }
}

and building, it gives me a Schema validation failed with the following errors: Data path ".index" should be string.

===========

UPDATE 10 Apr '20:

I just noticed that in October's update I missed a quote in the latest code snippet. I don't remember whether it was copied directly from my code - hence the reported error could be related to that - or it was a mistype when I attempted to rewrite the code. I'll check again whenever I'll have time



回答3:

With Angular 8 and 9 you can add custom webpack builder: https://github.com/just-jeb/angular-builders/tree/master/packages/custom-webpack

npm install @angular-builders/custom-webpack

and follow instructions from this page: https://github.com/just-jeb/angular-builders/blob/master/packages/custom-webpack/README.md



回答4:

this aint pretty but it works, i just have 2 index files and i copy over the main one before the build

"build:en": "copy src\\index.en.html src\\index.html && ng build --configuration=production-en",
"build:fr": "copy src\\index.fr.html src\\index.html && ng build --configuration=production-fr",


回答5:

If you want to stick with standard src/index.html while serving locally by want to have specialised index.html files per production / test configuration (as it was in my case, where different Google Analytics code chunks have been to be applied) do it simply:

  1. Create separate directories each holding a dedicated version of index.html. Eg.:

src/prod/index.html src/test/index.html

  1. Let angular.json know about them, per configuration:
"configurations": {
    "production": {
        "fileReplacements": [
            {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.prod.ts"
            }
        ],
        "index": "src/index/prod/index.html",
        // other stuff
    },
    "test": { 
        "fileReplacements": [
            {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.test.ts"
            }
        ],
        "index": "src/index/test/index.html",
        // other stuff
    }
    // other stuff
}