just-jeb / angular-builders

Angular build facade extensions (Jest and custom webpack configuration)
MIT License
1.14k stars 198 forks source link

The assets folder is not included on @angular-builders/custom-webpack:dev-server #759

Closed ZooLeeCoding closed 2 years ago

ZooLeeCoding commented 4 years ago

Describe the Bug

I have been using the @angular-builders package for over a year to load some very specific libraries into Angular and so far, everything was perfect. But recently I had to migrate this previous, Angular 7 app to Angular 9 and although everything seems to be working, every element of the assets folder throws 404 error, even though the assets folder is in the configuration of the custom builder and appears in its complete form if I choose to build the application instead of running it on the dev-server. Upon inspecting the source files served by the dev-server I am unable to find any trace of the assets folder.

Minimal Reproduction

  1. generate a new ionic project
  2. install @angular-builders and configure angular.json according to the official description
  3. start the project with ionic serve
  4. the assets folder won't be served, not even the default ionic favicon contained within

The contents of my angular.json:


{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "defaultProject": "app",
  "newProjectRoot": "projects",
  "projects": {
    "app": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": { "path": "./custom-webpack.config.js" },
            "outputPath": "www",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/assets",
              "src/assets/**/*"
            ],
            "styles": [
              {
                "input": "src/theme/variables.scss"
              },
              {
                "input": "src/global.scss"
              }
            ],
            "scripts": [],
            "es5BrowserSupport": true
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                }
              ]
            },
            "ci": {
              "progress": false
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "app:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "app:build:production"
            },
            "ci": {
              "progress": false
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "app:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "styles": [],
            "scripts": [],
            "assets": [
              {
                "glob": "favicon.ico",
                "input": "src/",
                "output": "/"
              },
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "/assets"
              }
            ]
          },
          "configurations": {
            "ci": {
              "progress": false,
              "watch": false
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": ["**/node_modules/**"]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "app:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "app:serve:production"
            },
            "ci": {
              "devServerTarget": "app:serve:ci"
            }
          }
        },
        "ionic-cordova-build": {
          "builder": "@ionic/angular-toolkit:cordova-build",
          "options": {
            "browserTarget": "app:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "app:build:production"
            }
          }
        },
        "ionic-cordova-serve": {
          "builder": "@ionic/angular-toolkit:cordova-serve",
          "options": {
            "cordovaBuildTarget": "app:ionic-cordova-build",
            "devServerTarget": "app:serve"
          },
          "configurations": {
            "production": {
              "cordovaBuildTarget": "app:ionic-cordova-build:production",
              "devServerTarget": "app:serve:production"
            }
          }
        }
      }
    }
  },
  "cli": {
    "defaultCollection": "@ionic/angular-toolkit"
  },
  "schematics": {
    "@ionic/angular-toolkit:component": {
      "styleext": "scss"
    },
    "@ionic/angular-toolkit:page": {
      "styleext": "scss"
    }
  }
}

The custom-webpack.js:


const path = require("path");
const vtkRules = require('vtk.js/Utilities/config/dependency.js').webpack.core.rules;
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
    module: {
        rules: [].concat(vtkRules)
    },
    plugins: [
        new CopyPlugin([{
                from: path.join(__dirname, 'node_modules', 'itk', 'WebWorkers'),
                to: path.join(__dirname, 'www', 'itk', 'WebWorkers')
            },
            {
                from: path.join(__dirname, 'node_modules', 'itk', 'ImageIOs'),
                to: path.join(__dirname, 'www', 'itk', 'ImageIOs')
            },
            {
                from: path.join(__dirname, 'node_modules', 'itk', 'MeshIOs'),
                to: path.join(__dirname, 'www', 'itk', 'MeshIOs')
            }
        ])
    ]
};

Expected Behavior

To have the assets folder served on the dev-server

Screenshots

The errors in the console log: image

If I build the project, everything is fine, runs without any issue if served with external application: image

Environment


Libs
"@angular/core": "~9.1.6"
"@angular-devkit/build-angular": "^0.901.7",
"@angular-builders/custom-webpack": "^9.1.0",

For Tooling issues:
- Node version: v12.16.3
- Platform:  Windows

Others:
 "@ionic-native/core": "^5.0.7",
 "@ionic-native/splash-screen": "^5.0.0",
 "@ionic-native/status-bar": "^5.0.0",
 "@ionic/angular": "^5.0.0",

Additional Context

The very same configuration run flawlessly on Angular 7 with "@angular-builders/custom-webpack": "^7.3.1", "@angular-builders/dev-server": "^7.3.1",

just-jeb commented 3 years ago

Any chance #235 is related?

dotupNET commented 3 years ago

Any chance #235 is related? @just-jeb No. I tried this config with functions instead of returning and object and it doesn't serve assets:

const webpack = require('webpack');
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');

module.exports = function (env, argv) {
    console.log(env);
    console.log(argv);
    return {
        mode: 'development',
        plugins: [
            new webpack.NormalModuleReplacementPlugin(/typeorm$/, function (result) {
                result.request = result.request.replace(/typeorm/, "typeorm/browser");
            }),
            new webpack.ProvidePlugin({
                'window.SQL': path.join(__dirname, '../node_modules/sql.js/dist/sql-asm.js'),
            }),
            new CopyPlugin(
                {

                    patterns: [{

                        from: 'node_modules/reflect-metadata/Reflect.js',
                        to: 'Reflect.js'
                    }]
                }),
        ],
        node: {
            fs: 'empty',
        },
    };
}

My angular.json:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "defaultProject": "app",
  "newProjectRoot": "projects",
  "projects": {
    "app": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./config/webpack.asm.js"
            },
            "outputPath": "www",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "assets"
              },
              {
                "glob": "**/*.svg",
                "input": "node_modules/ionicons/dist/ionicons/svg",
                "output": "./svg"
              }
            ],
            "styles": [
              {
                "input": "src/theme/variables.scss"
              },
              {
                "input": "src/global.scss"
              }
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "customWebpackConfig": {
                "path": "./config/webpack.wasm.js"
              },
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "serviceWorker": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                }
              ]
            },
            "ci": {
              "progress": false
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "app:build",
            "disableHostCheck": true,
            "proxyConfig": "proxy.config.json"
          },
          "configurations": {
            "production": {
              "customWebpackConfig": {
                "path": "./config/webpack.asm.js"
              },
              "browserTarget": "app:build:production"
            },
            "ci": {
              "progress": false
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "app:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "styles": [
              {
                "input": "src/theme/variables.scss"
              },
              {
                "input": "src/global.scss"
              }
            ],
            "scripts": [],
            "assets": [
              {
                "glob": "favicon.ico",
                "input": "src/",
                "output": "/"
              },
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "/assets"
              }
            ]
          },
          "configurations": {
            "ci": {
              "progress": false,
              "watch": false
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "app:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "app:serve:production"
            },
            "ci": {
              "devServerTarget": "app:serve:ci"
            }
          }
        },
        "ionic-cordova-build": {
          "builder": "@ionic/angular-toolkit:cordova-build",
          "options": {
            "browserTarget": "app:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "app:build:production"
            }
          }
        },
        "ionic-cordova-serve": {
          "builder": "@ionic/angular-toolkit:cordova-serve",
          "options": {
            "cordovaBuildTarget": "app:ionic-cordova-build",
            "devServerTarget": "app:serve"
          },
          "configurations": {
            "production": {
              "cordovaBuildTarget": "app:ionic-cordova-build:production",
              "devServerTarget": "app:serve:production"
            }
          }
        }
      }
    }
  },
  "cli": {
    "defaultCollection": "@ionic/angular-toolkit"
  },
  "schematics": {
    "@ionic/angular-toolkit:component": {
      "styleext": "scss"
    },
    "@ionic/angular-toolkit:page": {
      "styleext": "scss"
    }
  }
}

packages:

  "dependencies": {
    "@angular-builders/custom-webpack": "^10.0.1",
    "@angular/common": "~10.0.0",
    "@angular/core": "~10.0.0",
    "@angular/forms": "~10.0.0",
    "@angular/platform-browser": "~10.0.0",
    "@angular/platform-browser-dynamic": "~10.0.0",
    "@angular/pwa": "~0.1000.0",
    "@angular/router": "~10.0.0",
    "@angular/service-worker": "^10.0.14",
    "@capacitor/core": "2.4.3",
    "@ionic-native/core": "^5.0.0",
    "@ionic-native/in-app-browser": "^5.30.0",
    "@ionic-native/splash-screen": "^5.0.0",
    "@ionic-native/status-bar": "^5.0.0",
    "@ionic/angular": "^5.0.0",
    "@ionic/storage": "^2.3.1",
    "rxjs": "~6.5.5",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1000.0",
    "@angular/cli": "~10.0.5",
    "@angular/compiler": "~10.0.0",
    "@angular/compiler-cli": "~10.0.0",
    "@angular/language-service": "~10.0.0",
    "@capacitor/cli": "2.4.3",
    "@ionic/angular-toolkit": "^2.3.0",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~3.3.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~3.9.5"
  },
just-jeb commented 3 years ago

Hi @dotupNET. In order to be able to understand what's happening here I'm gonna need a minimal reproduction repo.
But I'm not sure I understand your issue. Why are you trying to copy files from node_modules instead of just bundling them?
What does assets folder have to do with it? Is this happening only with dev-server and working well with ng build?

bernatgy commented 2 years ago

We have the exact same issue. Huge angular app got upgraded from Angular 9 to 13. Had to do it all over once because custom-webpack blocked angular migrations to angular.json, so second time started by completely removing custom-webpack.

When I reached 13 and everything was working fine, even did some code migrations and refactoring, I reinstalled the custom-webpack builder, and assets just stopped being served.

They're there in the ng build output, but not in the ng serve'd up bundle.

We're using the custom-webpack builder to include mozilla PDF.js's worker script (that is loaded internally by filename) with a contenthash from node_modules. Weirdly enough, this works!

My guess is, it's related to https://github.com/just-jeb/angular-builders/issues/235 but I haven't tried using a function yet. Even tried force-using the newest copy-webpack-plugin, without any luck;

npm list copy-webpack-plugin
+-- @angular-devkit/build-angular@13.3.9
| `-- copy-webpack-plugin@10.2.1
`-- copy-webpack-plugin@11.0.0

npm list webpack
`-- @angular-devkit/build-angular@13.3.9
  `-- webpack@5.70.0

package.json

{
    "name": "app",
    "version": "1.0.0",
    "private": true,
    "dependencies": {
        "@angular/animations": "13.3.11",
        "@angular/common": "13.3.11",
        "@angular/compiler": "13.3.11",
        "@angular/core": "13.3.11",
        "@angular/forms": "13.3.11",
        "@angular/localize": "13.3.11",
        "@angular/platform-browser": "13.3.11",
        "@angular/platform-browser-dynamic": "13.3.11",
        "@angular/router": "13.3.11",
                ...
        "@stomp/rx-stomp": "^1.1.4",
        "reset-css": "^5.0.1",
        "rxjs": "6.6.3",
        "text-encoding": "0.7.0",
        "tslib": "^2.0.0",
        "zone.js": "~0.11.4"
    },
    "devDependencies": {
        "@angular-builders/custom-webpack": "^13.1.0",
        "@angular-devkit/build-angular": "13.3.9",
        "@angular/cli": "13.3.9",
        "@angular/compiler-cli": "13.3.11",
        "@angular/language-service": "^13.3.11",
        "typescript": "4.6.4",
        "webpack-manifest-plugin": "^5.0.0"
    },
    "scripts": {
        ...
    }
}

angular.json (with added comments)

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "cli": {
        "analytics": false,
        "cache": {
            "enabled": false
        }
    },
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "app": {
            ...
            "root": "",
            "sourceRoot": "src",
            "projectType": "application",
            "schematics": {
                "@schematics/angular:component": {
                    "style": "scss"
                }
            },
            "architect": {
                "build": {
                    "builder": "@angular-builders/custom-webpack:browser",
                    "defaultConfiguration": "production",
                    "options": {
                        "outputPath": "dist",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "tsConfig": "src/tsconfig.json",
                        "polyfills": "src/polyfills.ts",
                        "inlineStyleLanguage": "scss",
                        "customWebpackConfig": {
                            "path": "./extra-webpack.config.ts",
                            // As far as I could tell this changed from mergeStrategies to Rules,
                            // but the same thing happened with Rules too.
                            "mergeRules": {
                                "plugins": "append"
                            },
                            "replaceDuplicatePlugins": false
                        },
                        "assets": [
                            "src/assets",
                            "src/favicon.ico",
                            "src/unsupported-browser.html",
                            {
                                "glob": "**/*",
                                "input": "./node_modules/pdfjs-dist/cmaps/",
                                "output": "./assets/cmaps/"
                            }
                        ],
                        "styles": [
                            ...
                        ],
                        "scripts": [
                            "node_modules/text-encoding/lib/encoding-indexes.js",
                            "node_modules/text-encoding/lib/encoding.js",
                            "node_modules/pdfjs-dist/build/pdf.min.js",
                            "node_modules/pdfjs-dist/web/pdf_viewer.js"
                        ]
                    },
                    "configurations": {
                        "development": {
                            "aot": true,
                            "baseHref": "/",
                            "vendorChunk": true,
                            "extractLicenses": false,
                            "buildOptimizer": false,
                            "sourceMap": {
                                "scripts": true,
                                "styles": false,
                                "hidden": false,
                                "vendor": false
                            },
                            "optimization": false,
                            "namedChunks": true
                        },
                        ...
                        "production": {
                            "budgets": [
                                {
                                    "type": "anyComponentStyle",
                                    "maximumWarning": "6kb"
                                }
                            ],
                            "optimization": {
                                "fonts": false,
                                "styles": {
                                    "inlineCritical": false
                                }
                            },
                            "outputHashing": "bundles",
                            "aot": true,
                            "sourceMap": {
                                "scripts": true,
                                "styles": false,
                                "hidden": true,
                                "vendor": false
                            },
                            "namedChunks": false,
                            "extractLicenses": true,
                            "vendorChunk": false,
                            "buildOptimizer": true,
                            "baseHref": "/app/"
                        }
                    }
                },
                "serve": {
                    "builder": "@angular-builders/custom-webpack:dev-server",
                    "defaultConfiguration": "development",
                    "options": {
                        "browserTarget": "app:build",
                        "disableHostCheck": true
                    },
                    "configurations": {
                        "bernatgy": {
                            // NOTE: Using targets like this to simplify configuration works with default builders!
                            "browserTarget": "app:build:development,bernatgy,en",
                            // DHCP IP of the local PC
                            "host": "xxx.xxx.xxx.xx"
                        },
                        ...
                    }
                }
            }
        }
    },
    "defaultProject": "app"
}

extra-webpack.config.ts

import { Configuration } from 'webpack';
import * as CopyPlugin from 'copy-webpack-plugin';
import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
import * as path from 'path';
import { FileDescriptor } from 'webpack-manifest-plugin/dist/helpers';

let originalWorkerFilePath = require.resolve(`pdfjs-dist/build/pdf.worker.min.js`);

export default {
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: originalWorkerFilePath,
                    to: '[name].[contenthash].[ext]'
                }
            ]
        }),
        new WebpackManifestPlugin({
            filter: (file: FileDescriptor) => {
                if (file.name.indexOf(path.basename(originalWorkerFilePath)) !== -1)
                    return true;
                return false;
            },
            writeToFileEmit: true
        })
    ]
} as Configuration;
bernatgy commented 2 years ago

UPDATE: Works with the function form from https://github.com/just-jeb/angular-builders/issues/235#issuecomment-471323007!

We have the exact same issue. Huge angular app got upgraded from Angular 9 to 13. Had to do it all over once because custom-webpack blocked angular migrations to angular.json, so second time started by completely removing custom-webpack.

When I reached 13 and everything was working fine, even did some code migrations and refactoring, I reinstalled the custom-webpack builder, and assets just stopped being served.

They're there in the ng build output, but not in the ng serve'd up bundle.

We're using the custom-webpack builder to include mozilla PDF.js's worker script (that is loaded internally by filename) with a contenthash from node_modules. Weirdly enough, this works!

My guess is, it's related to #235 but I haven't tried using a function yet. Even tried force-using the newest copy-webpack-plugin, without any luck;

npm list copy-webpack-plugin
+-- @angular-devkit/build-angular@13.3.9
| `-- copy-webpack-plugin@10.2.1
`-- copy-webpack-plugin@11.0.0

npm list webpack
`-- @angular-devkit/build-angular@13.3.9
  `-- webpack@5.70.0

package.json

{
  "name": "app",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
      "@angular/animations": "13.3.11",
      "@angular/common": "13.3.11",
      "@angular/compiler": "13.3.11",
      "@angular/core": "13.3.11",
      "@angular/forms": "13.3.11",
      "@angular/localize": "13.3.11",
      "@angular/platform-browser": "13.3.11",
      "@angular/platform-browser-dynamic": "13.3.11",
      "@angular/router": "13.3.11",
                ...
      "@stomp/rx-stomp": "^1.1.4",
      "reset-css": "^5.0.1",
      "rxjs": "6.6.3",
      "text-encoding": "0.7.0",
      "tslib": "^2.0.0",
      "zone.js": "~0.11.4"
  },
  "devDependencies": {
      "@angular-builders/custom-webpack": "^13.1.0",
      "@angular-devkit/build-angular": "13.3.9",
      "@angular/cli": "13.3.9",
      "@angular/compiler-cli": "13.3.11",
      "@angular/language-service": "^13.3.11",
      "typescript": "4.6.4",
      "webpack-manifest-plugin": "^5.0.0"
  },
  "scripts": {
      ...
  }
}

angular.json (with added comments)

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "cli": {
      "analytics": false,
      "cache": {
          "enabled": false
      }
  },
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
      "app": {
          ...
          "root": "",
          "sourceRoot": "src",
          "projectType": "application",
          "schematics": {
              "@schematics/angular:component": {
                  "style": "scss"
              }
          },
          "architect": {
              "build": {
                  "builder": "@angular-builders/custom-webpack:browser",
                  "defaultConfiguration": "production",
                  "options": {
                      "outputPath": "dist",
                      "index": "src/index.html",
                      "main": "src/main.ts",
                      "tsConfig": "src/tsconfig.json",
                      "polyfills": "src/polyfills.ts",
                      "inlineStyleLanguage": "scss",
                      "customWebpackConfig": {
                          "path": "./extra-webpack.config.ts",
                          // As far as I could tell this changed from mergeStrategies to Rules,
                          // but the same thing happened with Rules too.
                          "mergeRules": {
                              "plugins": "append"
                          },
                          "replaceDuplicatePlugins": false
                      },
                      "assets": [
                          "src/assets",
                          "src/favicon.ico",
                          "src/unsupported-browser.html",
                          {
                              "glob": "**/*",
                              "input": "./node_modules/pdfjs-dist/cmaps/",
                              "output": "./assets/cmaps/"
                          }
                      ],
                      "styles": [
                          ...
                      ],
                      "scripts": [
                          "node_modules/text-encoding/lib/encoding-indexes.js",
                          "node_modules/text-encoding/lib/encoding.js",
                          "node_modules/pdfjs-dist/build/pdf.min.js",
                          "node_modules/pdfjs-dist/web/pdf_viewer.js"
                      ]
                  },
                  "configurations": {
                      "development": {
                          "aot": true,
                          "baseHref": "/",
                          "vendorChunk": true,
                          "extractLicenses": false,
                          "buildOptimizer": false,
                          "sourceMap": {
                              "scripts": true,
                              "styles": false,
                              "hidden": false,
                              "vendor": false
                          },
                          "optimization": false,
                          "namedChunks": true
                      },
                      ...
                      "production": {
                          "budgets": [
                              {
                                  "type": "anyComponentStyle",
                                  "maximumWarning": "6kb"
                              }
                          ],
                          "optimization": {
                              "fonts": false,
                              "styles": {
                                  "inlineCritical": false
                              }
                          },
                          "outputHashing": "bundles",
                          "aot": true,
                          "sourceMap": {
                              "scripts": true,
                              "styles": false,
                              "hidden": true,
                              "vendor": false
                          },
                          "namedChunks": false,
                          "extractLicenses": true,
                          "vendorChunk": false,
                          "buildOptimizer": true,
                          "baseHref": "/app/"
                      }
                  }
              },
              "serve": {
                  "builder": "@angular-builders/custom-webpack:dev-server",
                  "defaultConfiguration": "development",
                  "options": {
                      "browserTarget": "app:build",
                      "disableHostCheck": true
                  },
                  "configurations": {
                      "bernatgy": {
                          // NOTE: Using targets like this to simplify configuration works with default builders!
                          "browserTarget": "app:build:development,bernatgy,en",
                          // DHCP IP of the local PC
                          "host": "xxx.xxx.xxx.xx"
                      },
                      ...
                  }
              }
          }
      }
  },
  "defaultProject": "app"
}

extra-webpack.config.ts

import { Configuration } from 'webpack';
import * as CopyPlugin from 'copy-webpack-plugin';
import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
import * as path from 'path';
import { FileDescriptor } from 'webpack-manifest-plugin/dist/helpers';

let originalWorkerFilePath = require.resolve(`pdfjs-dist/build/pdf.worker.min.js`);

export default {
  plugins: [
      new CopyPlugin({
          patterns: [
              {
                  from: originalWorkerFilePath,
                  to: '[name].[contenthash].[ext]'
              }
          ]
      }),
      new WebpackManifestPlugin({
          filter: (file: FileDescriptor) => {
              if (file.name.indexOf(path.basename(originalWorkerFilePath)) !== -1)
                  return true;
              return false;
          },
          writeToFileEmit: true
      })
  ]
} as Configuration;