firebase-tools icon indicating copy to clipboard operation
firebase-tools copied to clipboard

Angular SSR 17 in Firebase : listen EADDRINUSE: address already in use :::8080

Open alexcibotari opened this issue 1 year ago • 11 comments

[REQUIRED] Environment info

firebase-tools: 13.0.2

Platform: Windows, Linux

[REQUIRED] Test case

I deploy a fully workable version from the emulator in Firebase Functions of the Angular SSR application.

[REQUIRED] Steps to reproduce

  • Enabled experiment webframeworks.
  • Create an application angular ssr from cli with standalone componenet
  • run it locally
  • deploy it in the firebase. During Local build I have next warning
▲ [WARNING] Module 'undici' used by 'node_modules/@firebase/auth/dist/node-esm/index.js' is not ESM
▲ [WARNING] Module '@grpc/grpc-js' used by 'node_modules/@firebase/firestore/dist/index.node.mjs' is not ESM
▲ [WARNING] Module '@grpc/proto-loader' used by 'node_modules/@firebase/firestore/dist/index.node.mjs' is not ESM
▲ [WARNING] Module 'undici' used by 'node_modules/@firebase/functions/dist/esm-node/index.node.esm.js' is not ESM
▲ [WARNING] Module 'undici' used by 'node_modules/@firebase/storage/dist/node-esm/index.node.esm.js' is not ESM
  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

[REQUIRED] Expected behavior

Should work exactly as in the emulator.

[REQUIRED] Actual behavior

SSR Page returns: Service Unavailable

Logs

Default STARTUP TCP probe succeeded after 1 attempt for container "ssr-project-name-1" on port 8080.

Uncaught exception

Error: listen EADDRINUSE: address already in use :::8080
    at Server.setupListenHandle [as _listen2] (node:net:1872:16)
    at listenInCluster (node:net:1920:12)
    at Server.listen (node:net:2008:7)
    at te.listen (file:///workspace/dist/ssr-project-name/server/server.mjs:81:3210)

at $k (file:///workspace/dist/ssr-project-name/server/server.mjs:99:5579)
at file:///workspace/dist/ssr-project-name/server/server.mjs:99:5665
at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
 at async importModuleDynamicallyWrapper (node:internal/vm/module:431:15)

Error: Process exited with code 16
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:92:22)
    at process.emit (node:events:514:28)
    at process.emit (node:domain:488:12)
    at process.exit (node:internal/process/per_thread:193:15)
    at sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:44:9)
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:84:44)
    at process.emit (node:events:526:35)
    at process.emit (node:domain:488:12)
    at process._fatalException (node:internal/process/execution:159:25)

alexcibotari avatar Dec 29 '23 20:12 alexcibotari

I have the same problem, I have published a repo with the minimum to recreate the SSR problem with angular 17: https://github.com/hittten/angularSSR17

Clone & Setup:

git clone https://github.com/hittten/angularSSR17
npm install
npx firebase init hosting

Logs:

=== Account Setup

Which account do you want to use for this project? Choose an account or add a new one now

? Please select an option: [email protected]

✔  Using account: [email protected]

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: xxxxxxx(xxxxxxx)
i  Using project xxxxxxx (xxxxxxx)

=== Hosting Setup
? Detected an existing Angular codebase in the current directory, should we use this? Yes
? In which region would you like to host server-side content, if applicable? europe-west1 (Belgium)
? Set up automatic builds and deploys with GitHub? No

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!

Deploy to firebase hosting with SSR function

npx firebase deploy

Server logs:

Error: listen EADDRINUSE: address already in use :::8080
    at Server.setupListenHandle [as _listen2] (node:net:1872:16)
    at listenInCluster (node:net:1920:12)
    at Server.listen (node:net:2008:7)
    at te.listen (file:///workspace/dist/angular-ssr17/server/server.mjs:81:3210)

Error: Process exited with code 16
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:92:22)
    at process.emit (node:events:514:28)
    at process.emit (node:domain:488:12)
    at process.exit (node:internal/process/per_thread:193:15)
    at sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:44:9)
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:84:44)
    at process.emit (node:events:526:35)
    at process.emit (node:domain:488:12)
    at process._fatalException (node:internal/process/execution:159:25)
{
  "textPayload": "The request failed because either the HTTP response was malformed or connection to the instance had an error. Additional troubleshooting documentation can be found at: https://cloud.google.com/run/docs/troubleshooting#malformed-response-or-connection-error",
  "insertId": "659475b700062cb90f40d1e3",
  "httpRequest": {
    "requestMethod": "GET",
    "requestUrl": "https://fh-8d3e45905df6630b---ssrfirebase-project-ou4f5ridea-ew.a.run.app/home",
    "requestSize": "1456",
    "status": 503,
    "responseSize": "896",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "remoteIp": "xx.xx.xx.xx",
    "serverIp": "xx.xx.xx.xx",
    "latency": "0.003751506s",
    "protocol": "HTTP/1.1"
  },
  "resource": {
    "type": "cloud_run_revision",
    "labels": {
      "revision_name": "ssrfirebase-project-00049-suv",
      "service_name": "ssrfirebase-project",
      "location": "europe-west1",
      "configuration_name": "ssrfirebase-project",
      "project_id": "firebase-project"
    }
  },
  "timestamp": "2024-01-02T20:44:39.398780Z",
  "severity": "ERROR",
  "labels": {
    "instanceId": "0087599d42b9441d6d09db1939ddd4cf4272e2926a4f28f80a4a7435e09c496814eec2631eed5c4f41d11da415f43dbdd4584eebf9300d2775bc6e376358218de7",
    "goog-managed-by": "cloudfunctions"
  },
  "logName": "projects/firebase-project/logs/run.googleapis.com%2Frequests",
  "trace": "projects/firebase-project/traces/2cbddcb349eb67f0b870211ea2050942",
  "receiveTimestamp": "2024-01-02T20:44:39.688582619Z",
  "spanId": "15678518055140550732"
}

Info

basically I have created a project like this:

npx @angular/[email protected] new angularSSR17 --ssr --routing --scss --skip-tests
cd angularSSR17
npm i -D [email protected]
ng g c pages/homePage
ng g c pages/aboutPage
ng g c pages/notFoundPage

I also disable pre-render in angular.json:

{
    "scripts": [],
    "server": "src/main.server.ts",
    "prerender": false,
    "ssr": {
      "entry": "server.ts"
    }
}

and I have done the settings of the routes for lazy load. I have not installed @angular/fire because it is not necessary to recreate the SSR error.

ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 17.0.8
Node: 20.10.0
Package Manager: npm 10.2.5
OS: darwin arm64

Angular: 17.0.8
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router, ssr

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1700.8
@angular-devkit/build-angular   17.0.8
@angular-devkit/core            17.0.8
@angular-devkit/schematics      17.0.8
@schematics/angular             17.0.8
rxjs                            7.8.1
typescript                      5.2.2
zone.js                         0.14.2

firebase-tools version:

13.0.2

hittten avatar Jan 02 '24 20:01 hittten

Hi @hittten,

I discovered a workaround that can be applied to the code of an Angular application. For example in the server.ts, https://github.com/hittten/angularSSR17/blob/2ed948581d32b20b45c66e8c4f4f72046d9a5cf4/server.ts#L46-L54 adjust a way of setting port variable. It looks like the PORT environment variable is already used. The solution could be:

  1. const port = process.env['NG_SSR_PORT'] || 4000; // change the environment variable name
  2. const port = 4000; // hardcode the port value without using environment variable

I don't know what exactly is the root cause, but as I mentioned it looks like PORT environment variable is already used.

9kubczas4 avatar Jan 08 '24 18:01 9kubczas4

Getting the same error:

Error: listen EADDRINUSE: address already in use :::8080
    at Server.setupListenHandle [as _listen2] (node:net:1817:16)
    at listenInCluster (node:net:1865:12)
    at Server.listen (node:net:1953:7)
    at te.listen (file:///workspace/dist/lucas-app/server/server.mjs:81:3210)
    at Mk (file:///workspace/dist/lucas-app/server/server.mjs:99:5579)
    at file:///workspace/dist/lucas-app/server/server.mjs:99:5665
    at ModuleJob.run (node:internal/modules/esm/module_job:195:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:336:24)
    at async importModuleDynamicallyWrapper (node:internal/vm/module:429:15)

mvergarair avatar Jan 12 '24 17:01 mvergarair

  1. const port = process.env['NG_SSR_PORT'] || 4000; // change the environment variable name
  2. const port = 4000; // hardcode the port value without using environment variable

I don't know what exactly is the root cause, but as I mentioned it looks like PORT environment variable is already used.

@9kubczas4 Thanks for information. This works well!

Add info:

If you deploy index.html, Functions will not work and must be IGNORED.

  {
    "source": ".",
    "frameworksBackend": {
      "region": "asia-east1"
    },
    "ignore": [
+    "index.html",

rdlabo avatar Jan 19 '24 09:01 rdlabo

@rdlabo thanks. Removing this process.env['NG_SSR_PORT'] worked

But will this be fixed in future releases in angular

JGSolutions avatar Jan 21 '24 14:01 JGSolutions

Thank you for your comment, but in which file can I find it?

{ "source": ".", "frameworksBackend": { "region": "asia-east1" }, "ignore": [

  • "index.html",

MoCodeCom avatar Jan 26 '24 12:01 MoCodeCom

  1. const port = process.env['NG_SSR_PORT'] || 4000; // change the environment variable name
  2. const port = 4000; // hardcode the port value without using environment variable

I don't know what exactly is the root cause, but as I mentioned it looks like PORT environment variable is already used.

@9kubczas4 Thanks for information. This works well!

Add info:

If you deploy index.html, Functions will not work and must be IGNORED.

  {
    "source": ".",
    "frameworksBackend": {
      "region": "asia-east1"
    },
    "ignore": [
+    "index.html",

Thank you for your comment, but in which file can I find it? to make an addition

MoCodeCom avatar Jan 26 '24 12:01 MoCodeCom

Reserved environment variables are listed here: https://firebase.google.com/docs/functions/config-env?gen=2nd#reserved-names

gguy0406 avatar Feb 20 '24 02:02 gguy0406

// In cloud functions bootstrap.js
const app = import(`./dist/project/server/server.mjs`).then(server => server.app());
exports.handle = (req, res) => app.then(it => it(req, res));

It appears that the run() function generated by Angular CLI is unnecessary. I use an firebase instance in my backend, it seems to execute firebase initializeApp() twice, leading to an error.

gguy0406 avatar Feb 20 '24 03:02 gguy0406

@9kubczas4 your workaround works perfectly.

Any update about this? this issue doesn't happen in angular 16.

hittten avatar Feb 22 '24 20:02 hittten

Same problem here. Any news ?

makss68 avatar Mar 11 '24 20:03 makss68

Please for now try to apply this workaround for Angular 17: https://github.com/firebase/firebase-tools/issues/6651#issuecomment-1881647322.

I created a fix in angular-cli - https://github.com/angular/angular-cli/pull/27333, once it's merged then it'll be available in one of the future Angular releases.

9kubczas4 avatar Mar 22 '24 16:03 9kubczas4