Skip to content

Trouble bundling Firestore for Universal (ENOENT / app.firestore not a function) #2686

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

Closed
eburi opened this issue Nov 24, 2020 · 9 comments
Closed

Comments

@eburi
Copy link

eburi commented Nov 24, 2020

Version info

Angular: 10@latest & 11@latest - same result

Firebase: 8.1.1

AngularFire: 6.1.1

Node: 12

Was all working fine on Firebase with SSR setup following the angularfire Guide.
We upgraded Firebase JS SDK and in order to get SSR working again, we had to remove the following from angular.json :

            "externalDependencies": [
              "@firebase/firestore"
            ]

Hence the error TypeError: app.firestore is not a function disappeared and SSR was working again, except on a sub-page that actually tries to load from data from firestore. When rendering this through SSR, we got the error:

Unhandled Promise rejection: ENOENT: no such file or directory, open '/workspace/dist/carchecker-ui/server/src/protos/google/firestore/v1/firestore.proto'

Expected behavior

Get SSR working with Firestore.

Actual behavior

I can choose a halfway working SSR solution by removing externalDependencies in angular.json (server) that seems to render some of the pages or breaking with missing Proto-Buffer stuff.
Or break SSR entirely with the TypeError: app.firestore is not a function when having @firebase/firestore in externalDependencies in angular.json.

@jamesdaniels
Copy link
Member

jamesdaniels commented Nov 24, 2020

Checkout what I've done in my sample app to support this https://github.com/angular/angularfire/blob/master/sample/server.ts#L18. I used dir-loader to include the protos into the server build as a quick hack.

I'm considering what an official happy path here with the schematic might look like.

@jamesdaniels
Copy link
Member

Closing but pinning, since this isn't strictly AngularFire issue and there's a work-around.

@jamesdaniels jamesdaniels pinned this issue Nov 30, 2020
@jamesdaniels jamesdaniels changed the title SSR: TypeError: app.firestore is not a function Trouble bundling Firestore for Universal (ENOENT / app.firestore not a function) Nov 30, 2020
@jamesdaniels
Copy link
Member

Another solution FWIW is to add all the firebase and @firebase libs to externalDependencies, but I'm steering away from that since it seems with some small hacks @firebase/firestore is perfectly packable now.

@Karman40
Copy link

Karman40 commented Dec 1, 2020

@jamesdaniels please help me whate can i do wrong

  1. update to latest packages
  2. install -D dir-loader
  3. create firestore-protos.ts file from simple.
  4. add file to tsconfig.server.json file array.
  5. edit server.ts file (add line: import 'dir-loader!./firestore-protos';)

and this works as fine, yes?
Becouse a get more warning and error.

Afer build:
about 15 times x Warning: Conflict: Multiple assets emit different content to the same filename undefined
image

I found file with undifined name without extentions. Start with this code:
image
image

After when i started the server


[2020-12-01T13:01:19.393Z]  @firebase/firestore: Firestore (8.1.1): INTERNAL UNHANDLED ERROR:  Error: ENOENT: no such file or directory, open 'D:\Angular\konigs-art\dist\server\src\protos\google\firestore\v1\firestore.proto'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at fetch (D:\Angular\konigs-art\dist\server\main.js:1:711045)
    at Root.load (D:\Angular\konigs-art\dist\server\main.js:1:711449)
    at Root.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:711629)
    at Object.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:738719)
    at loadProtos (D:\Angular\konigs-art\dist\server\main.js:1:1171345)
    at newConnection (D:\Angular\konigs-art\dist\server\main.js:1:1171502)
    at OnlineComponentProvider.createDatastore (D:\Angular\konigs-art\dist\server\main.js:1:1178832)
    at OnlineComponentProvider. (D:\Angular\konigs-art\dist\server\main.js:1:1178010)
ERROR Error: Uncaught (in promise): ReferenceError: localStorage is not defined


ReferenceError: localStorage is not defined
    at CartService.initLocalStorage (D:\Angular\konigs-art\dist\server\main.js:1:1779429)
    at new CartService (D:\Angular\konigs-art\dist\server\main.js:1:1776698)
    at Object.CartService_Factory [as factory] (D:\Angular\konigs-art\dist\server\main.js:1:1780092)
    at R3Injector.hydrate (D:\Angular\konigs-art\dist\server\main.js:1:3817424)
    at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814443)
    at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
    at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
    at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
    at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
    at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
    at resolvePromise (D:\Angular\konigs-art\dist\server\main.js:1:3470156)
    at resolvePromise (D:\Angular\konigs-art\dist\server\main.js:1:3469097)
    at D:\Angular\konigs-art\dist\server\main.js:1:3471747
    at ZoneDelegate.invokeTask (D:\Angular\konigs-art\dist\server\main.js:1:3460775)
    at Object.onInvokeTask (D:\Angular\konigs-art\dist\server\main.js:1:4049343)
    at ZoneDelegate.invokeTask (D:\Angular\konigs-art\dist\server\main.js:1:3460665)
    at Zone.runTask (D:\Angular\konigs-art\dist\server\main.js:1:3453340)
    at drainMicroTaskQueue (D:\Angular\konigs-art\dist\server\main.js:1:3464383) {
  rejection: ReferenceError: localStorage is not defined
      at CartService.initLocalStorage (D:\Angular\konigs-art\dist\server\main.js:1:1779429)
      at new CartService (D:\Angular\konigs-art\dist\server\main.js:1:1776698)
      at Object.CartService_Factory [as factory] (D:\Angular\konigs-art\dist\server\main.js:1:1780092)
      at R3Injector.hydrate (D:\Angular\konigs-art\dist\server\main.js:1:3817424)
      at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814443)
      at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
      at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
      at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
      at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
      at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834),
  promise: ZoneAwarePromise [Promise] {
    __zone_symbol__state: 0,
    __zone_symbol__value: ReferenceError: localStorage is not defined
        at CartService.initLocalStorage (D:\Angular\konigs-art\dist\server\main.js:1:1779429)
        at new CartService (D:\Angular\konigs-art\dist\server\main.js:1:1776698)
        at Object.CartService_Factory [as factory] (D:\Angular\konigs-art\dist\server\main.js:1:1780092)
        at R3Injector.hydrate (D:\Angular\konigs-art\dist\server\main.js:1:3817424)
        at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814443)
        at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
        at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
        at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
        at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
        at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
  },
  zone:  Zone {
    _parent: Zone {
      _parent: null,
      _name: '',
      _properties: {},
      _zoneDelegate: [ZoneDelegate]
    },
    _name: 'angular',
    _properties: { isAngularZone: true, maybeDelayChangeDetection: false },
    _zoneDelegate:  ZoneDelegate {
      _taskCounts: [Object],
      zone: [Circular *1],
      _parentDelegate: [ZoneDelegate],
      _forkZS: null,
      _forkDlgt: null,
      _forkCurrZone: null,
      _interceptZS: null,
      _interceptDlgt: null,
      _interceptCurrZone: null,
      _invokeZS: [Object],
      _invokeDlgt: [ZoneDelegate],
      _invokeCurrZone: [Circular *1],
      _handleErrorZS: [Object],
      _handleErrorDlgt: [ZoneDelegate],
      _handleErrorCurrZone: [Circular *1],
      _scheduleTaskZS: [Object],
      _scheduleTaskDlgt: [ZoneDelegate],
      _scheduleTaskCurrZone: [Circular *1],
      _invokeTaskZS: [Object],
      _invokeTaskDlgt: [ZoneDelegate],
      _invokeTaskCurrZone: [Circular *1],
      _cancelTaskZS: [Object],
      _cancelTaskDlgt: [ZoneDelegate],
      _cancelTaskCurrZone: [Circular *1],
      _hasTaskZS: [Object],
      _hasTaskDlgt: [ZoneDelegate],
      _hasTaskDlgtOwner: [Circular *2],
      _hasTaskCurrZone: [Circular *1]
    }
  },
  task: ZoneTask {
    _zone:  Zone {
      _parent: [Zone],
      _name: 'angular',
      _properties: [Object],
      _zoneDelegate: [ZoneDelegate]
    },
    runCount: 0,
    _zoneDelegates: null,
    _state: 'notScheduled',
    type: 'microTask',
    source: 'Promise.then',
    data: ZoneAwarePromise [Promise] {
      __zone_symbol__state: 0,
      __zone_symbol__value: ReferenceError: localStorage is not defined
          at CartService.initLocalStorage (D:\Angular\konigs-art\dist\server\main.js:1:1779429)
          at new CartService (D:\Angular\konigs-art\dist\server\main.js:1:1776698)
          at Object.CartService_Factory [as factory] (D:\Angular\konigs-art\dist\server\main.js:1:1780092)
          at R3Injector.hydrate (D:\Angular\konigs-art\dist\server\main.js:1:3817424)
          at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814443)
          at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
          at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
          at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
          at R3Injector.get (D:\Angular\konigs-art\dist\server\main.js:1:3814653)
          at NgModuleRef$1.get (D:\Angular\konigs-art\dist\server\main.js:1:3999834)
    },
    scheduleFn: undefined,
    cancelFn: undefined,
    callback: [Function (anonymous)],
    invoke: [Function (anonymous)]
  }
}


Unhandled Promise rejection: ENOENT: no such file or directory, open 'D:\Angular\konigs-art\dist\server\src\protos\google\firestore\v1\firestore.proto' ; Zone:  ; Task: Promise.then ; Value: Error: ENOENT: no such file or directory, open 'D:\Angular\konigs-art\dist\server\src\protos\google\firestore\v1\firestore.proto'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at fetch (D:\Angular\konigs-art\dist\server\main.js:1:711045)
    at Root.load (D:\Angular\konigs-art\dist\server\main.js:1:711449)
    at Root.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:711629)
    at Object.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:738719)
    at loadProtos (D:\Angular\konigs-art\dist\server\main.js:1:1171345)
    at newConnection (D:\Angular\konigs-art\dist\server\main.js:1:1171502)
    at OnlineComponentProvider.createDatastore (D:\Angular\konigs-art\dist\server\main.js:1:1178832)
    at OnlineComponentProvider. (D:\Angular\konigs-art\dist\server\main.js:1:1178010) {
  errno: -4058,
  syscall: 'open',
  code: 'ENOENT',
  path: 'D:\\Angular\\konigs-art\\dist\\server\\src\\protos\\google\\firestore\\v1\\firestore.proto'
}


Error: ENOENT: no such file or directory, open 'D:\Angular\konigs-art\dist\server\src\protos\google\firestore\v1\firestore.proto'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at fetch (D:\Angular\konigs-art\dist\server\main.js:1:711045)
    at Root.load (D:\Angular\konigs-art\dist\server\main.js:1:711449)
    at Root.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:711629)
    at Object.loadSync (D:\Angular\konigs-art\dist\server\main.js:1:738719)
    at loadProtos (D:\Angular\konigs-art\dist\server\main.js:1:1171345)
    at newConnection (D:\Angular\konigs-art\dist\server\main.js:1:1171502)
    at OnlineComponentProvider.createDatastore (D:\Angular\konigs-art\dist\server\main.js:1:1178832)
    at OnlineComponentProvider. (D:\Angular\konigs-art\dist\server\main.js:1:1178010)

@jamesdaniels
Copy link
Member

I'm guessing your paths need to be altered in the firestore_protos.ts, this is a very new solution. The other as mentioned is to put every firebase dep in external 🤷‍♂

@Karman40
Copy link

Karman40 commented Dec 1, 2020

firestore_protos.ts file, i dont found any typo:

module.exports = {
  path: './node_modules/@firebase/firestore/dist/src/protos',
  filter: /\.proto$/,
  pathTransform: (path: string) => {
    const name = path.split('./node_modules/@firebase/firestore/dist/')[1];
    return `file-loader?name=${name}!${path}`;
  }
};

Are you saying I restore everything and use it as external dep?

@solivellaluisalberto
Copy link

When i add this to externalDependencies
"externalDependencies": [ "@firebase/app", "@firebase/firestore" ]
I no longer receive any errors, neither firestore.proto nor app.firestore is not a function
I don't know if this will help you.

@viktorsml
Copy link

When i add this to externalDependencies
"externalDependencies": [ "@firebase/app", "@firebase/firestore" ]
I no longer receive any errors, neither firestore.proto nor app.firestore is not a function
I don't know if this will help you.

I had the same issue, and this solves the problem, the other solutions above only introduced more errors for me. Thank you!!

@inorganik
Copy link

Can anyone get the sample app to build? I hit an error:

> ng build --prod && ng run sample:server:production

✔ Browser application bundle generation complete.

Error: The target entry-point "@angular/fire/analytics" has missing dependencies:
 - @angular/fire
 - @angular/fire/auth
 

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

No branches or pull requests

6 participants