Firebase-js-sdk: Importing firestore through npm package gives error message and wont load

Created on 12 May 2018  路  20Comments  路  Source: firebase/firebase-js-sdk

[REQUIRED] Describe your environment

  • Operating System version: Windows 10 1803
  • Firebase SDK version: 5.0.2
  • Firebase Product: database/firestore

[REQUIRED] Describe the problem

Trying to get Polymer 3.0 to work with firebase/firestore.
Wanted to use the npm packages, and after installing them i can module import firebase, but i get a reference error when i try to import the firestore package

Steps to reproduce:

  1. Download PWA Starter Kit
  2. npm install @firebase/app
  3. npm install @firebase/firestore
  4. add to "my-app.js":

import firebase from '@firebase/app';
import '@firebase/firestore';

error message i get is:

Uncaught TypeError: Failed to resolve module specifier "@firebase/app". Relative references must start with either "/", "./", or "../".

If i remove the second row (firestore), and just try to load @firebase/app, everything is fine, i can initialize firebase. But as soon as i add that second row, everything breaks.

core firestore

Most helpful comment

@ralcar I'm having the same issues and couldn't get it working using javascript imports. But the "old approach" with global namespace pollution still works in Polymer 3, so as a temporary workaround you can do the following:

  1. Have the global script imports for everything you need in index.html:
    <script src="/node_modules/firebase/firebase-app.js"></script>
    <script src="/node_modules/firebase/firebase-auth.js"></script>
    <script src="/node_modules/firebase/firebase-firestore.js"></script>
  1. Create a firebase.js file that does the initialization, ie. like below. This way you only need to touch that one file once the js imports of firebase work:
const config = {
    apiKey: "...",
    authDomain: "....firebaseapp.com",
    databaseURL: "https://.....firebaseio.com",
    projectId: "...",
};
firebase.initializeApp(config);

const firestore = firebase.firestore();
const settings = {
  timestampsInSnapshots: true,
};
firestore.settings(settings);

export default firebase;

export {
  firestore,
};
  1. In your components, you can now use:
// ...
import { firestore } from './firebase.js';

class MyGroups extends PolymerElement {
   // ...

  loadFirestoreGroups() {
    return firestore
      .collection('groups')
      .orderBy('name')
      .get()
      .then(snapshot => {
        const groups = [];
        snapshot.forEach(doc => {
          groups.push(doc.data());
        });

        return groups;
      });
  }
}

All 20 comments

@jshcrowthe Can you help?

Yeah I'll take a look. I have some suspicions around why this may be so I'll take this.

@jshcrowthe any idea how i can get around it?
Wanted to build my new project in Polymer 3 + Firestore, but having a hard time getting off the ground, not much info out there on how to go about.

@ralcar I'm having the same issues and couldn't get it working using javascript imports. But the "old approach" with global namespace pollution still works in Polymer 3, so as a temporary workaround you can do the following:

  1. Have the global script imports for everything you need in index.html:
    <script src="/node_modules/firebase/firebase-app.js"></script>
    <script src="/node_modules/firebase/firebase-auth.js"></script>
    <script src="/node_modules/firebase/firebase-firestore.js"></script>
  1. Create a firebase.js file that does the initialization, ie. like below. This way you only need to touch that one file once the js imports of firebase work:
const config = {
    apiKey: "...",
    authDomain: "....firebaseapp.com",
    databaseURL: "https://.....firebaseio.com",
    projectId: "...",
};
firebase.initializeApp(config);

const firestore = firebase.firestore();
const settings = {
  timestampsInSnapshots: true,
};
firestore.settings(settings);

export default firebase;

export {
  firestore,
};
  1. In your components, you can now use:
// ...
import { firestore } from './firebase.js';

class MyGroups extends PolymerElement {
   // ...

  loadFirestoreGroups() {
    return firestore
      .collection('groups')
      .orderBy('name')
      .get()
      .then(snapshot => {
        const groups = [];
        snapshot.forEach(doc => {
          groups.push(doc.data());
        });

        return groups;
      });
  }
}

@a-xin thats great! I will try that right away, thank you!
Any idea on how to avoid loading all the scripts in index.html, and try to lazy load them on specific views? (like the auth that is pretty big).

I saw in one of the pwa demos (books demo) that they lazy loaded the google auth by putting it in a redux action, and then loading it into the DOM "with document.head.appendChild(script);"

Feels like a lot of steps from previous solutions..

@ralcar Yeah, something like that should work. For my case, I'll be waiting for a fix and then use import('./firebase.js').then(...) to lazy-load firebase

@a-xin thanks for the reference!!

Appreciate the patience here folks.

I reached out to the Polymer team on this. Seems the new Polymer build tooling doesn't have support for CJS modules, only ESM. As part of Firestore we have a dependency on the @firebase/webchannel-wrapper package (code here) for our browser builds. The package is a wrapper around the Closure Library webchannel implementation that reexports things as a CJS module.

In principle (and I haven't gone down this road yet), we would need to also export an ESM build of that package. I would recommend either the workaround above, or if someone wanted to submit a PR to create and export an ESM build of that module, that'd be great.

However this isn't really a problem on the Firebase side, but the Polymer build tooling. Any module that doesn't export an ESM build, would experience similar issues.

cc: @justinfagnani

I'd 鉂わ笍 for firebase to lead the field and start publishing their web libraries as es modules instead of using other forms that require additional dependencies to run.
ES Modules are now supported across the board, they're the easiest form of code for either javascript or typescript developers to consume, and they don't need additional tooling聽to be consumed.

@jshcrowthe the webchannel-wrapper README looks like it supports JS modules:

import { WebChannel } from '@firebase/webchannel-wrapper'

Is that not true?

It'd be great to start pulling the yarn to unravel from CJS. There are some techniques available to load a subset of CJS via imports, especially if they're leaf modules. I can try to help there.

We are working on getting ESM support baked into all our modules but there are still some stragglers (notably @firebase/webchannel-wrapper and @firebase/auth)

The module itself is only used by the firestore team via TS which handles the ESM/CJS interop stuff for us. I agree we need to have an ESM build, just hasn't been a burning need as up till now most build chains either natively, or via plugins, work w/ CJS.

The Polymer build tooling not supporting CJS is definitely a forcing function to get that work done. However, I anticipate there will be many libs that will be impacted by the lack of CJS support. Maybe some specific error messaging on the Polymer side to say something like:

"Hey this module that you depend on (either directly, or transitively) doesn't export ES Modules"

Feels like that could be helpful.

"Hey this module that you depend on (either directly, or transitively) doesn't export ES Modules"

We'd have to implement some heuristics to do that, because what we see is imports to JS files. We don't know that they'll fail at runtime. We could see that a file has no exports and give a warning.

@jshcrowthe since this issue is closed, can we open another for a JS module compatible distribution so we can track it?

Also, to chime in a bit here. You shouldn't import modules using bare packages when using Polymer 3. So

import firebase from '@firebase/app';
import '@firebase/firestore';

wouldn't have worked anyway.

You need to specify /node_modules as part of your path.

import firebase from '/node_modules/@firebase/app';
import '/node_modules/@firebase/firestore';

Of course, it doesn't fix the issue of the package exports directly but just thought it would be helpful to mention this.

NOTE: If, in polymer 3, module resolution is set to node, I believe bare package identifiers will work, however. But I'm not sure if this would work in every use-case.

@mkay581 the Polymer tools do support node-style module resolution, so you can use package names in import specifiers.

Using an absolute path in imports would only work in cases where your web server mounted node_modules at the root.

Yeah I mentioned that in my edit to my comment haha

@a-xin Thanks for your example. It works nice when the app is served with polymer serve. However, when I package with polymer build and then serve with prpl-server, I get an error saying Uncaught SyntaxError: Export 'firebase' is not defined in module.

Also, at build time, I get a warning:

warn: [cli.build.optimize-streams]    js-transform: Unable to optimize /home/X/public/src/my-component.js 
{ err:
   'undefined: Exporting local "firebase", which is not declared.

despite the fact that index.html has global imports:

<script src="/node_modules/firebase/firebase-app.js"></script>
<script src="/node_modules/firebase/firebase-auth.js"></script>
<script src="/node_modules/firebase/firebase-database.js"></script>
<script src="/node_modules/firebase/firebase-firestore.js"></script>
<script src="/node_modules/firebase/firebase-functions.js"></script>
<script src="/node_modules/firebase/firebase-storage.js"></script>

Did you manage to package your app and make it work with Firebase?

It was working fine for me, both serve and build.
If it only works for serve, maybe you need to add firebase to extraDependencies in polymer.json. See:
https://www.polymer-project.org/3.0/docs/tools/polymer-json#extradependencies

@a-xin Thanks. Finally, I defined const firebase = window.firebase; in your copy of firebase.js and the build is passing (with no warnings) and work. Hope we can fully use Firebase with ES6 imports soon.

Run this and it will work smoothly. Worked for me.
npm cache clean --force

Was this page helpful?
0 / 5 - 0 ratings