Cannot set fileReplacements to replace folder content with Angular 11

9.5k views Asked by At

I'm using the angular cli config fileReplacements in angular.json file to replace a folder content, like this:

{
  "projects": {
    "myProject": {
      "architect": {
        "build": {
          "configurations": {
            "prod": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                },
                {
                  "replace": "node_modules/moment/locale/",
                  "with": "src/moment-js-locale/"
                }
              ]
            }
          }
        }
      }
    }
  }
}

Notice that in replace value I'm using a path to a folder instead of a path to a file. This is working code for Angular 10.

I upgraded to Angular 11 and now I'm getting an error when trying to build a prod version using this command: ng build --prod

The error I'm getting is:

Schema validation failed with the following errors:
  Data path ".fileReplacements[1]" should NOT have additional properties(replace).
  Data path ".fileReplacements[1].replace" should match pattern "\.(([cm]?j|t)sx?|json)$".
  Data path ".fileReplacements[1]" should match exactly one schema in oneOf.

ESLint is showing me this warning:

String does not match the pattern of "\.(([cm]?j|t)sx?|json)$".

What can I do with this? Is this an Angular 11 bug? should I use a different approach?

Any help will be appreciated.

3

There are 3 answers

4
benshabatnoam On BEST ANSWER

So it turns out that this feature was in fact a Bug The fact that one could make a folder replacement till Angular 10 wasn't supposed to work from the beginning.

I asked this question in angular-cli repo and this was the answer that I got:

I am sorry that you are experiencing this issue after updating. However, replacing directories was never a supported use-case of the file replacements feature.

I guess that this will need to be handled by the developer. In my case I just added a script to do that with shell command and I'm running this script as a pre build script using npm run script.

3
Drazu On

I was successful with following configuration for web.config and images dedicated for production (I put files for production into src/deployment/prod and they are copied to dist directory into directory from "output" variable):

"fileReplacements": [
    {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
    }
],
"assets": [
    "src/assets",
    "src/favicon.ico",
    {
        "input": "src/deployment/prod",
        "output": "/",
        "glob": "web.config"
    },
    {
        "input": "src/deployment/prod",
        "output": "assets/img",
        "glob": "*.png"
    }
]

so in your case you probably could use:

{
    "input": "node_modules/moment/locale/", -- source folder in ClientApp/
    "output": "moment-js-locale", -- destination folder in dist/
    "glob": "*.js" -- all js files will be copied
}
0
Jonathan On

To do this the right way, simply change the tsconfig file in your angular.json file.

For example:

"configurations": {
  "staging": {
    "customWebpackConfig": {
      "path": "./webpack.config.ts"
    },
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],
    "outputHashing": "all",
    "tsConfig": "tsconfig.app.staging.json"

And create a separate tsconfig.app.staging.json like so:

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "paths": {
      "@nav/*": [
        "src/app/nav/*"
      ]
    }
  }
}

You can put whatever relative paths you want, but keep in mind the "paths" variable will get replaced completely with whatever other values you have, since you're essentially redefining it.

J