angularserver-side-renderingangular-universalprerender

Angular 17 prerender doesn't work after update


Angular 16 uses @nguniversal/builders:prerender as a builder for Prerender which works fine, After upgrading to Angular 17 ng update changes this builder to @angular-devkit/build-angular:prerender and after running ng run <project-name>:prerender there's a warning which says An unhandled exception occurred: Configuration 'production' is not set in the workspace. I can't fix this error but it continues running after this error and writes ✔ Browser application bundle generation complete. ✔ Copying assets complete. ✔ Index html generation complete. but there's no prerendered page generated. here is my angular.json file:

    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "karlancer": {
            "projectType": "application",
            "schematics": {},
            "root": "",
            "sourceRoot": "src",
            "prefix": "app",
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                      "outputPath": "dist/karlancer",
                      "allowedCommonJsDependencies": [
                        "rxjs-compat",
                        "rxjs",
                        "hammerjs"
                      ],
                      "index": "src/index.html",
                      "main": "src/main.ts",
                      "polyfills": "src/polyfills.ts",
                      "tsConfig": "tsconfig.app.json",
                      "aot": true,
                      "assets": [
                        "src/assets",
                        "src/robots.txt"
                      ],
                      "styles": [
                        "src/styles.css",
                        "node_modules/bootstrap/dist/css/bootstrap.min.css"
                      ],
                      "scripts": [
                        "./node_modules/jquery/dist/jquery.js",
                        "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
                      ]
                    },
                    "configurations": {
                        "production": {
                            "fileReplacements": [{
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }],
                            "optimization": true,
                            "outputHashing": "all",
                            "sourceMap": false,
                            "namedChunks": false,
                            "extractLicenses": true,
                            "budgets": [{
                                    "type": "initial",
                                    "maximumWarning": "2mb",
                                    "maximumError": "6mb"
                                },
                                {
                                    "type": "anyComponentStyle",
                                    "maximumWarning": "6kb",
                                    "maximumError": "20kb"
                                }
                            ]
                        },
                        "development": {
                            "buildOptimizer": false,
                            "optimization": false,
                            "vendorChunk": true,
                            "extractLicenses": false,
                            "sourceMap": true,
                            "namedChunks": true
                          }
                    }
                },
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "options": {
                      "buildTarget": "karlancer:build"
                    },
                    "configurations": {
                        "production": {
                          "buildTarget": "karlancer:build:production"
                        },
                        "development": {
                          "buildTarget": "karlancer:build:development"
                        }
                    }
                },
                "extract-i18n": {
                    "builder": "@angular-devkit/build-angular:extract-i18n",
                    "options": {
                      "buildTarget": "karlancer: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",
                        "assets": [
                            "src/assets",
                            "src/robots.txt"
                        ],
                        "styles": [
                            "src/styles.css"
                        ],
                        "scripts": []
                    }
                },
                "e2e": {
                    "builder": "@angular-devkit/build-angular:protractor",
                    "options": {
                        "protractorConfig": "e2e/protractor.conf.js",
                        "devServerTarget": "karlancer:serve"
                    },
                    "configurations": {
                        "production": {
                            "devServerTarget": "karlancer:serve:production"
                        }
                    }
                },
                "server": {
                    "builder": "@angular-devkit/build-angular:server",
                    "options": {
                        "outputPath": "dist/karlancer/server",
                        "main": "server.ts",
                        "tsConfig": "tsconfig.server.json",
                        "optimization": false,
                        "buildOptimizer": false
                    }
                },
                "serve-ssr": {
                    "builder": "@angular-devkit/build-angular:ssr-dev-server",
                    "options": {
                      "browserTarget": "karlancer:build",
                      "serverTarget": "karlancer:server"
                    },
                    "configurations": {
                      "production": {
                        "browserTarget": "karlancer:build:production",
                        "serverTarget": "karlancer:server:production"
                      }
                    }
                },
                "prerender": {
                    "builder": "@angular-devkit/build-angular:prerender",
                    "options": {
                        "browserTarget": "karlancer:build:production",
                        "serverTarget": "karlancer:server:production",
                        "routes": [
                            "/"
                          ]
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "karlancer:build:production",
                            "serverTarget": "karlancer:server:production"
                        }
                    },
                    "defaultConfiguration": "production"
                }
            }
        }
    },
    "cli": {
        "analytics": false
    }
}

Which I found out the builder has changed from angular 17 as said in Angular documents

it can be updated with ng update @angular/cli --name use-application-builder command which changes the builder to application in that case the prerender is an option which is used in this builder. When you set that option to true or declare routes in it after building this error code appears Error: NG0908 it has been told in other resources this is due to polyfills.js being loaded after main.js but these loading sequences are out of my control. I need to run prerender on Angular 17 but I can't find an example on github or anything that works.


Solution

  • I had the same error with prerender after upgrading a project to angular 17. I checked out this working example on github where prerendering works with Angular 17 and the application builder: https://github.com/ganatan/angular-ssr

    The actual cause of the Error: NG0908 is when you specify the src/polyfills.ts file in the Angular.json "polyfills" option. In the example, 'zone.js' is directly declared in the "polyfills" options in the Angular.json.

    To solve the problem, in your Angular.json file, change from:

    "polyfills": "src/polyfills.ts"
    

    to this:

    "polyfills": ["zone.js"]
    

    I also removed the src/polyfills.ts from the tsconfig.app.json "files" list.