Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Page Not Found" after deploying SSR enabled Angular 17 application #6505

Closed
misomarcell opened this issue Nov 10, 2023 · 20 comments
Closed

Comments

@misomarcell
Copy link

misomarcell commented Nov 10, 2023

[REQUIRED] Environment info

firebase-tools: 12.8.1
@angular/core: "^17.0.1
@angular/common: "^17.0.1
@angular/compiler: "^17.0.0
@anguler/ssr: 17.0.0

Platform: Windows 11, 23H2

[REQUIRED] Test case

See the full repository here: https://github.com/misomarcell/fire-chat

firebase.json

"hosting": {
  "source": ".",
  "target": "fire-chat",
  "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
  "frameworksBackend": {
    "region": "europe-west1"
  }
}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "fire-chat": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": "public",
            "index": "src/index.html",
            "browser": "src/main.ts",
            "polyfills": ["zone.js"],
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": [
              "@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss"
            ],
            "scripts": [],
            "server": "src/main.server.ts",
            "prerender": true,
            "ssr": {
              "entry": "server.ts"
            }
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "outputHashing": "all"
            },
            "development": {
              "optimization": false,
              "extractLicenses": false,
              "sourceMap": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "configurations": {
            "production": {
              "buildTarget": "fire-chat:build:production"
            },
            "development": {
              "buildTarget": "fire-chat:build:development"
            }
          },
          "defaultConfiguration": "development"
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "buildTarget": "fire-chat:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "polyfills": ["zone.js", "zone.js/testing"],
            "tsConfig": "tsconfig.spec.json",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": [
              "@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss"
            ],
            "scripts": []
          }
        },
        "deploy": {
          "builder": "@angular/fire:deploy",
          "options": {
            "version": 2,
            "browserTarget": "fire-chat:build:production"
          }
        }
      }
    }
  },
}

[REQUIRED] Steps to reproduce

  • Create a new Angular 17 application via Anguler CLI: ng new
  • Enable dserver-side rendering
  • Add @angular/fire@17.0.0-next.0
  • Enabled webframeworks experiment firebase experiments:enable webframeworks
  • Initialize firebase-tools: firebase init
  • Deploy the aplication using firebase deploy

[REQUIRED] Expected behavior

A server-side rendered website loads when opening firebase web app.

[REQUIRED] Actual behavior

Page Not Found error displayed when opening the firebase web app.

Additional info

  • The app works as expected both serving locally using ng serve and using the hosting emulator.
  • Navigating to the hosted URL and then /browser loads the index.html, but due to 404, it can't load any of the assets, like js and css files, therefore it's just an empty white page without any content on it whatsoever.
  • I'd expect either a Cloud Run or a Firebase Function instance acting as the Frontend server, but there are non of either created after the deploy.
@misomarcell
Copy link
Author

Found the solution: angular/angularfire#3463 (comment)
Although would be nice to have these things properly set up on project creation.

@hittten
Copy link

hittten commented Nov 11, 2023

@misomarcell Is not a solution is the old way to use the builder. Angular v17 came with the new builder (see https://angular.dev/tools/cli/build):

@angular-devkit/build-angular:application Builds an application with a client-side bundle, a Node server, and build-time prerendered routes with esbuild.

That's why you don't need to separate de browser & server builders.

@misomarcell
Copy link
Author

@hittten The new approach of building the application in a bundle currently does not work with the Firebase deployment, that's why we need to separate the browser and the server. If you have a better solution to this problem, please educate us.

@ersimont
Copy link

This problem also occurs with non-SSR angular apps starting in v17. I suspect the reason is that in v17, a newly scaffolded app puts it build output in a different path.

Old : dist/project-name/
New: dist/project-name/browser

This is because, as hinted in the linked issue, a newly scaffolded app uses a new builder in angular.json:

Old: @angular-devkit/build-angular:browser
New: @angular-devkit/build-angular:application

A commenter on the linked issue shows they were able to fix it by reverting back to the old builder. The tooling needs to update to support the new builder. I'm not sure if that's the responsibility of this repo, or angularfire.

@hittten
Copy link

hittten commented Nov 11, 2023

@ersimont @misomarcell

I don't have the solution we have to wait for firebase-tools to make the fix to unterstand the new builder for angular 17: https://esbuild.github.io/

Let's see, I said that it was not a solution because in Angular 17 you can actually use the previous build. So if you really want to use the new build which is much faster and better than webpack, we don't have a solution/workaround for this yet.

There are two problems here:

  1. Not found page: This is because the firebase-tools don't know the route of the browser folder. In the previous version of angular.json, we had something like this:
{
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "outputPath": "dist/myApp/browser",
      "index": "src/index.html",
      "main": "src/main.ts",
      "polyfills": [
        "zone.js"
      ],
      "tsConfig": "tsconfig.app.json",
      "inlineStyleLanguage": "scss",
      "assets": [
        "src/favicon.ico",
        "src/assets"
      ],
      "styles": [
        "src/styles.scss"
      ],
      "scripts": []
    }
  },
  "server": {
    "builder": "@angular-devkit/build-angular:server",
    "options": {
      "outputPath": "dist/myApp/server",
      "main": "server.ts",
      "tsConfig": "tsconfig.server.json",
      "inlineStyleLanguage": "scss"
    },
    "configurations": {
      "production": {
        "outputHashing": "media"
      },
      "development": {
        "buildOptimizer": false,
        "optimization": false,
        "sourceMap": true,
        "extractLicenses": false,
        "vendorChunk": true,
        "fileReplacements": [
          {
            "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.development.ts"
          }
        ]
      }
    },
    "defaultConfiguration": "production"
  },
  "prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
      "guessRoutes": false,
      "routes": [
        "/"
      ]
    },
    "configurations": {
      "production": {
        "browserTarget": "myApp:build:production",
        "serverTarget": "myApp:server:production"
      },
      "development": {
        "browserTarget": "myApp:build:development",
        "serverTarget": "myApp:server:development"
      }
    },
    "defaultConfiguration": "production"
  }
}

As you can see, we have 3 builders here:

  {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "outputPath": "dist/myApp/browser"
    }
  },
  "server": {
    "builder": "@angular-devkit/build-angular:server",
    "options": {
      "outputPath": "dist/myApp/server"
    }
  },
  "prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
      "guessRoutes": false,
      "routes": [
        "/"
      ]
    }
  }
}

The "output path" determines where the correct folder is for each build: "browser" and "server". If you visit your hosting URL, "/browser", you will see the files, but with errors.

Now in angular 17 with the "@angular-devkit/build-angular:application" builder, the "angular.json" file should be simplified, but firebase-tools doesn't know how to handle it.

  1. The SSR Cloud Function: There is no evidence of implementation in the "firebase deploy" log, I see only hosting logs.

@hittten
Copy link

hittten commented Nov 11, 2023

@ersimont angularfire is not necessary for a Firebase web framework with SSR deploy. You can see this: https://firebase.google.com/docs/hosting/frameworks/angular The AngularFire is optinal

I have many websites with the minimal for SSR, you can try it:

npm i -g @angular/cli@16 @firebase-tools
ng new myApp --routing --style scss
ng add @nguniversal/express-engine
firebase experiments:enable webframeworks
firebase init hosting
firebase deploy

With this you should have an Angular application with firebase hosting and a ssr cloud function v2 (Cloud run)

@mvergarair
Copy link

mvergarair commented Nov 15, 2023

@jamesdaniels does this PR fix this issue? I'm having the same problem on angular 17.

@jamesdaniels
Copy link
Member

Angular v17 & application builder support is landing with #6480

@robin-james
Copy link

Hi, I'm noob but this solution seems to work :

1. $ ng build
2. $ Firebase init
(*) Hosting : Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
Hosting Setup
? Detected an existing Angular codebase in the current directory, should we use this? No
? Do you want to use a web framework? (experimental) No

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? dist/myapp/browser
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? No
Wrote dist/myapp/browser/404.html
? File dist/MyApp/browser/index.html already exists. Overwrite? No

=> firebase.json
"hosting": { "public": "dist/myapp/browser", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] }

3. $ Firebase deploy

Preview in DevTools => Network, seems good
angular17hosting

@FranzStrudel
Copy link

@robin-james Doing this, you serve the application statically, but does not enable SSR

@robin-james
Copy link

@FranzStrudel

How can I check if the SSR is working ? When I inspect the source code (ctrl+u) all the html appears correctly h1 etc... This was not the case with the old versions it seems to me.

@FranzStrudel
Copy link

FranzStrudel commented Nov 24, 2023

@robin-james

You might have prerender enabled (it is by default)

Set prerender to false in your angular.json and try again.

Note that if you don't have dynamic server side logic (based on auth cookie for instance) you might just go with your setup

@sonallux
Copy link
Contributor

If anyone wants to try the upcoming support for Angular 17 SSR Apps and can not wait for an official release, you can use "firebase-tools": "firebase/firebase-tools#master" in your package.json. This will use the current master branch from this repository which already contains the changes from #6480 🚀

@alexdabast
Copy link

alexdabast commented Nov 28, 2023

@sonallux thank you with your trick I was able to deploy on firebase it looked ok but it was only pre-rendering that was fine
SSR is throwing an error
Error: listen EADDRINUSE: address already in use :::8080
But I can find why port 8080 is being used by. I can't find anywhere in google cloud platform this information

@sonallux
Copy link
Contributor

@sonallux thank you with your trick I was able to deploy on firebase it looked ok but it was only pre-rendering that was fine
SSR is throwing an error
Error: listen EADDRINUSE: address already in use :::8080
But I can find why port 8080 is being used by. I can't find anywhere in google cloud platform this information

I had the same issue. You must remove the run() function in your server.ts file. The express server is started by firebase automatically.

@alexdabast
Copy link

@sonallux thank you again and you seems to understand angular SSR pretty well.
I'm facing a other issue:
We are using directus as "backend" and using their official directus/sdk who is a plain javascript library. So SSR is not rendering any content called by this sdk. If I use HttpClient to do the same request it is working fine.

So I assume that because under the hood the directus/sdk do not use anything related to angular SSR is not kicking in.

Any suggestion on how I could include standard library in the SSR process ?

@misomarcell
Copy link
Author

misomarcell commented Dec 5, 2023

Seems like after installing the version of the master branch, the hosting function is being deployed automatically as well, but I'm still getting the old Page Not Found error, plus looking at the SSR function's log, it's still seems to compiled incorrectly: TypeError: require(...).app is not a function

@9kubczas4
Copy link
Contributor

Hi @misomarcell,
I was able to deploy some demo Angular v17 app with basic routing to Firebase using master version of the firebase-tools. The deployment went without problems, and also deployed app works.
I've prepared a simple repository: https://github.com/9kubczas4/ng-firebase-deploy-test.

I've a question, are you deploying master branch from this repository: https://github.com/misomarcell/fire-chat?

@sonallux
Copy link
Contributor

sonallux commented Dec 5, 2023

@sonallux thank you again and you seems to understand angular SSR pretty well.
I'm facing a other issue:
We are using directus as "backend" and using their official directus/sdk who is a plain javascript library. So SSR is not rendering any content called by this sdk. If I use HttpClient to do the same request it is working fine.

So I assume that because under the hood the directus/sdk do not use anything related to angular SSR is not kicking in.

Any suggestion on how I could include standard library in the SSR process ?

The problem is that the request is not executed in a macro task through Zone.js. See this Stack overflow answer for more details.

@jamesdaniels
Copy link
Member

Closing this issue as v17 support has landed on latest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests